首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有比使用CountDownLatch更好的方法等待两个线程完成它们的任务吗?

有比使用CountDownLatch更好的方法等待两个线程完成它们的任务吗?
EN

Stack Overflow用户
提问于 2016-09-17 12:00:19
回答 1查看 2.5K关注 0票数 4

我的要求是在启动依赖作业之前等待两个线程完成执行。

为了做到这一点,我能够创建一个CountDownLatch和一个Waiter Thread,它将等待CountDownLatch变为零。一个约束是我不能使用主线程等待两个线程完成。主线程继续执行其他任务。

这东西确实有用。然而,我觉得在这方面的解决办法比坚实的设计。

我的问题如下:

  1. 目前的方法有哪些明显的缺陷?eg伪信号
  2. 你会推荐什么样的设计?

我现在的代码是:

代码语言:javascript
复制
class Waiter implements Runnable {
    private CountDownLatch latch; 

    Waiter (CountDownLatch latch){
        this.latch = latch;
    }

    @Override
    public void run() {
        System.out.println("Waiter Started running..." + latch.getCount());

        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Waiter ready to trigger Next Job!");
    }
}

class Processor implements Runnable {
    private CountDownLatch latch; 

    Processor (CountDownLatch latch){
        this.latch = latch;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        latch.countDown();
    }
}

public class CountDownLatchDemo {
    public static void main (String[] args) throws InterruptedException{
        CountDownLatch latch = new CountDownLatch(2);

        ExecutorService executor = Executors.newFixedThreadPool(2);
        for (int i=0; i< 2; i++){
            executor.submit(new Processor(latch));
        }

        ExecutorService waitExecutor = Executors.newFixedThreadPool(2);
        waitExecutor.submit(new Waiter(latch));

        Thread.sleep(3000);
        executor.shutdown();
        waitExecutor.shutdown();
        System.out.println("Keep doing other things! Sleep here is just for help you run this code for test!");
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-17 17:44:05

CountDownLatch是适合您的任务的解决方案。但是Java 8提供了另一种选择- CompletableFuture。您可以为您的任务创建两个这样的未来,然后使用其中一个方法等待期货完成并异步执行其他内容。例如:

代码语言:javascript
复制
// Submit Task 1
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
    }
    System.out.println("Task 1 completed");
    return 5;
});
// Submit Task 2
CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(3000);
    } catch (InterruptedException e) {
    }
    System.out.println("Task 2 completed");
    return 7;
});
// This call will create a future that will wait for f1 and f2 to complete
// and then execute the runnable
CompletableFuture.allOf(f1, f2).thenRun(() -> {
    System.out.println("Both completed");
});

所有这些调用都将异步处理,您的主线程将继续运行。如果在第三个任务中需要前两个任务的结果,可以使用thenAcceptBothAsync()而不是allOf()

代码语言:javascript
复制
f1.thenAcceptBothAsync(f2, (a, b) -> System.out.println("Result = " + (a + b)));

CompletableFuture中有许多方法允许您创建异步执行的任务链。JVM使用默认的ForkJoinPool来执行它们,但是您可以提供您自己的Executor来完成您的未来,并使用它们完成许多其他有用的事情。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39546565

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档