多线程 实现高效多借口调用

正常情况下我们调用多借口,都会顺序调用,也就是串行,如果借口直接没有任何关系,而串行执行消耗的时间,就是各个借口直接调用的总和。而jdk其实给我们提供有返回值类型线程,可以解决这个问题。

测试基类:用于统计执行时间

复制代码
import org.apache.commons.lang.StringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;

import com.ms.cloud.common.util.frame.SpObserver;

@RunWith(SpringRunner.class)
public class BaseTest {

    
    private Long starttime;
    @Rule
    public TestName junitClass= new TestName();
    @Before
    public void before() {
        starttime = System.currentTimeMillis();
        setDataSource();
        System.out.println(junitClass.getMethodName() + "....................start....................");
    }
    @After
    public void after() {
        double usedtime = (System.currentTimeMillis() - starttime) / 1000.0;
        System.out.println("耗时  " + usedtime + " ms");
        System.out.println(junitClass.getMethodName() + "....................end....................");
    }

    protected void setDataSource() {
        this.setDataSource(null, null);
    }
    protected void setDataSource(String city, String sourceType) {
        if (StringUtils.isEmpty(city)) {
            city = "sz";
        }
        if (StringUtils.isEmpty(sourceType)) {
            sourceType = "PC";
        }
        SpObserver.putSoruce(sourceType);
        SpObserver.putSp(city);
    }
    
}
复制代码

工具类,模拟用户调用多借口。每个接口消耗几秒钟。。

复制代码
import java.util.concurrent.TimeUnit;

public class UserUtils {

    public static String getHead(String uid) throws InterruptedException {
        TimeUnit.SECONDS.sleep(2);
        return ""+uid+"】的头";
    }
    public static String getFace(String uid)throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        return ""+uid+"】的脸";
    }
    public static String getFoot(String uid) throws InterruptedException {
        TimeUnit.SECONDS.sleep(7);
        return ""+uid+"】的脚";
    }
}
复制代码

正常情况下我们执行程序如此:

普通人:

复制代码
import org.junit.Test;

public class MyGodTest extends BaseTest {

    @Test
    public void testDo() throws InterruptedException {
        String uid = "路人甲";
        StringBuffer sb = new StringBuffer();
        sb.append(UserUtils.getHead(uid)).append("\n");
        sb.append(UserUtils.getFace(uid)).append("\n");
        sb.append(UserUtils.getFoot(uid)).append("\n");
        System.out.println("信息为:\n" + sb.toString());
    }
}
复制代码

直接串联:执行结果耗时14+s

testDo....................start....................
信息为:
【路人甲】的头
【路人甲】的脸
【路人甲】的脚

耗时 14.016 ms testDo....................end....................

 

老程序员:

开启多线程,异步模式。用线程池与不用都可以。。让线程跑起来就行

复制代码
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

import org.junit.Test;

/**
 * @desc 采用线程方式 
 * @author 陈惟鲜 chenweixian
 * @date 2020年7月23日 下午1:00:23
 *
 */
public class MyGodThreadTest extends BaseTest {

    /**用线程执行
     * @throws InterruptedException
     * @throws ExecutionException
     */
    @Test
    public void testDo() throws InterruptedException, ExecutionException {
        String uid = "路人甲";
        StringBuffer sb = new StringBuffer();
        Callable<String> headCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getHead(uid);
            }
        };
        
        Callable<String> faceCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getFace(uid);
            }
        };
        
        Callable<String> footCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getFoot(uid);
            }
        };
        // 
        FutureTask<String> headFutureTask = new FutureTask<>(headCallable);
        FutureTask<String> faceFutureTask = new FutureTask<>(faceCallable);
        FutureTask<String> footFutureTask = new FutureTask<>(footCallable);
        
        // 执行方法,线程异步执行
        new Thread(headFutureTask).start();
        new Thread(faceFutureTask).start();
        new Thread(footFutureTask).start();
        
        sb.append(headFutureTask.get()).append("\n");
        sb.append(faceFutureTask.get()).append("\n");
        sb.append(footFutureTask.get()).append("\n");
        System.out.println("信息为:\n" + sb.toString());
    }
    
    /**用线程池执行
     * @throws InterruptedException
     * @throws ExecutionException
     */
    @Test
    public void testPoolDo() throws InterruptedException, ExecutionException {
        String uid = "路人甲";
        StringBuffer sb = new StringBuffer();
        Callable<String> headCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getHead(uid);
            }
        };
        
        Callable<String> faceCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getFace(uid);
            }
        };
        
        Callable<String> footCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getFoot(uid);
            }
        };
        // 
        FutureTask<String> headFutureTask = new FutureTask<>(headCallable);
        FutureTask<String> faceFutureTask = new FutureTask<>(faceCallable);
        FutureTask<String> footFutureTask = new FutureTask<>(footCallable);
        
        // 执行方法,线程异步执行
        ExecutorService executor = Executors.newCachedThreadPool();
        executor.submit(headFutureTask);
        executor.submit(faceFutureTask);
        executor.submit(footFutureTask);
        executor.shutdown();
        
        sb.append(headFutureTask.get()).append("\n");
        sb.append(faceFutureTask.get()).append("\n");
        sb.append(footFutureTask.get()).append("\n");
        System.out.println("线程池信息为:\n" + sb.toString());
    }
}
复制代码

执行结果:7+s

testPoolDo....................start....................
线程池信息为:
【路人甲】的头
【路人甲】的脸
【路人甲】的脚

耗时  7.02 ms
testPoolDo....................end....................

 

总结:

多学多看,多实践,对工作有帮助。

核心部分如下

复制代码
Callable<String> footCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getFoot(uid); == 业务处理
            }
        };
FutureTask<String> headFutureTask = new FutureTask<>(headCallable);
new Thread(faceFutureTask).start(); ==执行程序
footFutureTask.get() ==得到响应结果
复制代码

 




posted on   陈惟鲜的博客  阅读(514)  评论(0编辑  收藏  举报

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示