前言
线程中run方法调用CountDownLatch。CountDownLatch的两个核心方法:
- countObj.countDown() 表示countObj计数减少。
- countObj.await() 表示检查countObj若不为0则阻塞,为0,则允许执行。
比较
join
join的工作原理是(源码),不停检查thread是否存活,如果存活则让当前线程永远wait,直到thread线程终止,线程的this.notifyAll 就会被调用。
CountDownLatch
检查计数器是否为0,如果不为0则让当前线程永远wait,直到thread线程中的计数器为0,线程的this.notifyAll 就会被调用。
方式1: 用join实现三个线程有序执行
public static void main(String[] args) {
final Thread t1=new Thread(new Runnable(){
@Override
public void run() {
System.out.println("t1");
}
});
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try{
t1.join();
}catch(InterruptedException e){
}
System.out.println("t2");
}
});
final Thread t3=new Thread(new Runnable(){
@Override
public void run() {
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t3");
}
});
t1.start();
t2.start();
t3.start();
}
方式2: 用CountDownLatch实现三个线程有序执行
创建线程类的时候,将上一个计数器和本线程计数器传入。运行前业务执行上一个计数器.await,执行后本计数器.countDown。
public class CountLatchDown3 {
public static void main(String[] args) {
CountDownLatch c0 = new CountDownLatch(0); //①
CountDownLatch c1 = new CountDownLatch(1); //②
CountDownLatch c2 = new CountDownLatch(1); //③
Thread t1 = new Thread(new Work(c0, c1));
//c0为0,t1可以执行。t1的计数器减1
Thread t2 = new Thread(new Work(c1, c2));
//t1的计数器为0时,t2才能执行。t2的计数器c2减1
Thread t3 = new Thread(new Work(c2, c2));
//t2的计数器c2为0时,t3才能执行
t2.start();
t1.start();
t3.start();
}
//定义Work线程类,需要传入开始和结束的CountDownLatch参数
static class Work implements Runnable {
CountDownLatch c1;
CountDownLatch c2;
Work(CountDownLatch c1, CountDownLatch c2){
super();
this.c1=c1;
this.c2=c2;
}
public void run() {
try {
c1.await();//前一线程为0才可以执行
System.out.println("开始执行线程:"+ Thread.currentThread().getName());
c2.countDown();//本线程计数器减少
} catch (InterruptedException e) {
}
}
}
}
效果:
开始执行线程:Thread-0
开始执行线程:Thread-1
开始执行线程:Thread-2
注:将上述代码①②③处全部写CountDownLatch(0),则不会造成线程阻塞。会有如下随机结果:
开始执行线程:Thread-1
开始执行线程:Thread-0
开始执行线程:Thread-2