Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 有没有比使用倒计时闩锁更好的方法等待两个线程完成任务?_Java_Multithreading_Locking - Fatal编程技术网

Java 有没有比使用倒计时闩锁更好的方法等待两个线程完成任务?

Java 有没有比使用倒计时闩锁更好的方法等待两个线程完成任务?,java,multithreading,locking,Java,Multithreading,Locking,我的要求是在启动依赖作业之前,等待两个线程完成执行 为此,我可以创建一个倒计时闩锁和一个服务员线程,等待倒计时闩锁变为零。一个限制是我不能使用主线程等待两个线程完成。主线程继续执行其他任务 这东西确实有用。然而,我觉得这比一个坚实的设计更能解决问题 我的问题如下: 目前的方法有哪些明显的缺陷?伪信号 你推荐什么设计 我当前的代码: class Waiter implements Runnable { private CountDownLatch latch; Waiter (

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

为此,我可以创建一个
倒计时闩锁
和一个
服务员
线程
,等待
倒计时闩锁
变为零。一个限制是我不能使用主线程等待两个线程完成。主线程继续执行其他任务

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

我的问题如下:

  • 目前的方法有哪些明显的缺陷?伪信号
  • 你推荐什么设计
  • 我当前的代码:

    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!");
        }
    }
    
    类服务员实现可运行{
    私人倒计时闩锁;
    服务员(倒计时闩锁){
    this.latch=闩锁;
    }
    @凌驾
    公开募捐{
    System.out.println(“服务员开始运行…”+latch.getCount());
    试一试{
    satch.wait();
    }捕捉(中断异常e){
    e、 printStackTrace();
    }
    System.out.println(“服务员准备触发下一个作业!”);
    }
    }
    类处理器实现可运行{
    私人倒计时闩锁;
    处理器(倒计时锁存器){
    this.latch=闩锁;
    }
    @凌驾
    公开募捐{
    试一试{
    睡眠(300);
    }捕捉(中断异常e){
    e、 printStackTrace();
    }
    倒计时();
    }
    }
    公共类倒计时{
    公共静态void main(字符串[]args)引发InterruptedException{
    倒计时闩锁=新倒计时闩锁(2);
    ExecutorService executor=Executors.newFixedThreadPool(2);
    对于(int i=0;i<2;i++){
    执行人提交(新处理器(闩锁));
    }
    ExecutorService waitExecutor=Executors.newFixedThreadPool(2);
    waitExecutor.submit(新服务员(闩锁));
    睡眠(3000);
    executor.shutdown();
    waitExecutor.shutdown();
    println(“继续做其他事情!在这里睡觉只是为了帮助您运行测试代码!”);
    }
    }
    
    倒计时闩锁
    是适合您的任务的解决方案。但是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");
    });
    

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

    我觉得这很好。较低级别的替代方法是在两个线程上调用join()。join需要位于我想要避免的主线程中,因为我需要该线程继续执行其他任务。在这种情况下,使用CountDownLatch是一种完全有效的方法,无需使其更复杂不,可以将两个工作线程传递给服务员线程,并从服务员线程调用join()。但正如我所说,使用倒计时闩锁是完全可以的。我要说的唯一一句话是在finally block中调用countDown(),否则您的服务员会等很久。这看起来更干净。
    f1.thenAcceptBothAsync(f2, (a, b) -> System.out.println("Result = " + (a + b)));