都用与阻塞线程
Join
情景:
假设一条流水线上有三个工作者:worker0,worker1,worker2。有一个任务的完成需要他们三者协作完成,worker2可以开始这个任务的前提是worker0和worker1完成了他们的工作,而worker0和worker1是可以并行他们各自的工作的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public class Worker extends Thread { //工作者名 private String name; //工作时间 private long time; public Worker(String name, long time) { this.name = name; this.time = time; } @Override public void run() { // TODO 自动生成的方法存根 try { System.out.println(name+"开始工作"); Thread.sleep(time); System.out.println(name+"工作完成,耗费时间="+time); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } |
Test类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class Test { public static void main(String[] args) throws InterruptedException { // TODO 自动生成的方法存根 Worker worker0 = new Worker("worker0", (long) (Math.random()*2000+3000)); Worker worker1 = new Worker("worker1", (long) (Math.random()*2000+3000)); Worker worker2 = new Worker("worker2", (long) (Math.random()*2000+3000)); worker0.start(); worker1.start(); worker0.join(); worker1.join(); System.out.println("准备工作就绪"); worker2.start(); } } |
输出:
1 2 3 4 5 6 7 |
worker1开始工作 worker0开始工作 worker1工作完成,耗费时间=3947 worker0工作完成,耗费时间=4738 准备工作就绪 worker2开始工作 worker2工作完成,耗费时间=4513 |
CountDownLatch
情景:
假设worker的工作可以分为两个阶段,work2 只需要等待work0和work1完成他们各自工作的第一个阶段之后就可以开始自己的工作了,而不是场景1中的必须等待work0和work1把他们的工作全部完成之后才能开始。
Work类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
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() { // TODO 自动生成的方法存根 try { System.out.println(name+"开始工作"); 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类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class Test { public static void main(String[] args) throws InterruptedException { // TODO 自动生成的方法存根 CountDownLatch countDownLatch = new CountDownLatch(2); Worker worker0 = new Worker("worker0", (long) (Math.random()*2000+3000CountDownLatch与join的区别:调用thread.join() 方法必须等thread 执行完毕,当前线程才能继续往下执行,而CountDownLatch通过计数器提供了更灵活的控制,只要检测到计数器为0当前线程就可以往下执行而不用管相应的thread是否执行完毕。), 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(); } |
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
worker0开始工作 worker1开始工作 worker1第一阶段工作完成 worker0第一阶段工作完成 准备工作就绪 worker2开始工作 worker1第二阶段工作完成 worker1工作完成,耗费时间=5521 worker0第二阶段工作完成 worker0工作完成,耗费时间=6147 worker2第一阶段工作完成 worker2第二阶段工作完成 worker2工作完成,耗费时间=5384 |
CountDownLatch与join的区别:调用thread.join() 方法必须等thread 执行完毕,当前线程才能继续往下执行,而CountDownLatch通过计数器提供了更灵活的控制,只要检测到计数器为0当前线程就可以往下执行而不用管相应的thread是否执行完毕。