CountDownLatch和join的区别

版权声明:博客欢迎转载,但转载请亲们注明出处链接! https://blog.csdn.net/klordy_123/article/details/89142386

  蚂蚁一面被问到这个问题,当时实在是想不到两者在实现相同功能时的区别,回来百度了一下,发现其实还是蛮简单的问题哈。
  首先,两者都能够实现阻塞线程等待完成后,再继续进行后续逻辑,对于两者相同的功能这里不再赘述,我们直接说说它们之间的区别,考虑一个场景,我们的主线程阻塞到某处,等待其它线程完成某些操作之后再继续后续操作,具体就是主线程M,等待子线程T1和T2完成某项操作,但是子线程T1和T2中的任务可能有很多事情要做,而其中只有中间某一步完成后,其实就可以唤醒主线程继续执行,而不需要等待子线程所有任务执行完毕再执行主线程。这种情况下,如果通过调用子线程的join方法来卡住主线程,那么主线程就必须等待子线程所有任务全部执行完毕,才能继续执行,这种情况下效率是极其低下甚至不可行的,此时就必须要用CountDownLatch来实现更加细粒度的任务控制,示例代码如下:

  • Worker.java
public class Worker extends Thread {  
    private String name;  
    private long time;  
      
    private CountDownLatch countDownLatch;  
      
    public Worker(String name, long time, CountDownLatch countDownLatch) {  
        this.name = name;  
        this.time = time;  
        this.countDownLatch = countDownLatch;  
    }  
      
    @Override  
    public void run() {  
        try {  
            Thread.sleep(time);  
            System.out.println(name+"第一阶段工作完成");  
              
            countDownLatch.countDown();  
              
            Thread.sleep(2000); //这里就姑且假设第二阶段工作都是要2秒完成  
            System.out.println(name+"第二阶段工作完成");  
            System.out.println(name+"工作完成,耗费时间="+(time+2000));  
              
        } catch (InterruptedException e) {  
            // TODO 自动生成的 catch 块  
            e.printStackTrace();  
        }     
    }  
}  
  • Test.java
public class Test {  
    public static void main(String[] args) throws InterruptedException {  
        CountDownLatch countDownLatch = new CountDownLatch(2);  
        Worker worker0 = new Worker("worker0", (long) (Math.random()*2000+3000), countDownLatch);  
        Worker worker1 = new Worker("worker1", (long) (Math.random()*2000+3000), countDownLatch);  
        Worker worker2 = new Worker("worker2", (long) (Math.random()*2000+3000), countDownLatch);  
          
        worker0.start();  
        worker1.start();      
        countDownLatch.await();  
          
        System.out.println("准备工作就绪");  
        worker2.start();  
    }  
}  

  以上代码work0work1只需要执行完第一阶段的任务主线程work2就可以开始执行了,如果用join的话,就必须要等待work0work1的所有任务执行完毕,work2就需要无故等待两秒中再执行,所以显然此时用CountDownLatch是更加合适的。
参考:https://blog.csdn.net/nyistzp/article/details/51444487

猜你喜欢

转载自blog.csdn.net/klordy_123/article/details/89142386