有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java有没有比使用CountDownLatch更好的等待两个线程完成任务的方法?

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

为了做到这一点,我可以创建一个CountDownLatch和一个Waiter{}来等待CountDownLatch变为零。一个限制是我不能使用主线程来等待两个线程完成。主线程继续执行其他任务

这东西确实有用。然而,我觉得这比一个坚实的设计更能解决问题

我的问题如下:

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

我当前的代码:

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!");
    }
}

共 (1) 个答案

  1. # 1 楼答案

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

    // 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()

    f1.thenAcceptBothAsync(f2, (a, b) -> System.out.println("Result = " + (a + b)));
    

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