如何并发执行多个任务并等待执行结果?


一、为什么要并发执行多个任务,而不是一个个顺序执行呢?

比如一个接口执行了A、B、C三个任务,分别耗时1、2、3秒,如果顺序执行的话,总耗时需要6秒,代码如下:

public class TestExecuteClass {
    @Test
    public void entrance() {
        String resultA = executeTaskA();
        String resultB = executeTaskB();
        String resultC = executeTaskC();
        // ...
    }
    
    public String executeTaskA() {
        // 耗时1s
    }
    
    public String executeTaskB() {
        // 耗时2s
    }
    
    public String executeTaskC() {
        // 耗时3s
    }
}

很明显会很慢,也不会完全发挥我们多CPU的优势。所以如果我们可以并行执行这几个任务,再阻塞去获取执行结果,那么总耗时是会大大减少的。

二、如何并发执行多个任务并等待执行结果?

1、使用线程池(常用)

使用线程池可以使用多个线程并行执行多个任务,来充分发挥多CPU的优势,代码如下:

public class TestExecuteClass {
    
    private ExecutorService executor = Executors.newFixedThreadPool(10);
    
    public void entrance() throws Exception{
        Future<String> futureA = executor.submit(()->executeTaskA());
        Future<String> futureB = executor.submit(()->executeTaskB());
        Future<String> futureC = executor.submit(()->executeTaskC());
        
        String resultA = futureA.get();
        String resultA = futureA.get();
        String resultA = futureA.get();
        // ...
    }
    
    public String executeTaskA() {
        // 耗时1s
    }

    public String executeTaskB() {
        // 耗时2s
    }

    public String executeTaskC() {
        // 耗时3s
    }
}

2、使用CompletableFuture

CompletableFuture是JDK8引入的异步编程工具量类,代码如下:

public class TestExecuteClass {
    public void entrance() {
        CompleatableFuture<String> futureA = CompletableFuture.supplyAsync(()-> executeTaskA());
        CompleatableFuture<String> futureB = CompletableFuture.supplyAsync(()-> executeTaskB());
        CompleatableFuture<String> futureC = CompletableFuture.supplyAsync(()-> executeTaskC());
        
        String resultA = futureA.get();
        String resultB = futureB.get();
        String resultC = futureC.get();
        // ...
    }

    public String executeTaskA() {
        // 耗时1s
    }

    public String executeTaskB() {
        // 耗时2s
    }

    public String executeTaskC() {
        // 耗时3s
    }
}

3、使用CountDownLatch

CountDownLatch是Java中的一个同步类,在构造的时候指定一个计数值,表示需要等待的事件数量(每当一个事件到达,则计数值减一)。当计数值减为零时,当前线程才会继续被唤醒执行。

public class TaskExecuteClass {
    public void entrance() throws Exception{
        // 创建计数值为3的CountDownLatch,表示需要等待3个事件完成才能继续执行
        CountDownLatch countDownLatch = new CountDownLatch(3);
        
        executeTaskA();
        executeTaskB();
        executeTaskC();
        
        // 阻塞,直到3个事件完成才能继续执行
        countDownLatch.await();
        
        // ...
    }
    public String executeTaskA() {
        // 耗时1s
    }

    public String executeTaskB() {
        // 耗时2s
    }

    public String executeTaskC() {
        // 耗时3s
    }
}

文章作者: GaryLee
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 GaryLee !
  目录