都用与阻塞线程
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是否执行完毕。