CountDownLatch:
CountDownLatch是一个非常实用的多线程控制工具类,称之为“倒计时器”,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。
public class Main6Activity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main6);
//创建countDownLatch 对象
final CountDownLatch countDownLatch = new CountDownLatch(5);
for(int i = 0; i<5; i++){
final int finalI = i;
new Thread(new Runnable() {
@Override
public void run() {
Log.e("TAG","线程"+ finalI+"执行完成");
//调用countDown()方法
countDownLatch.countDown();
}
}).start();
}
try {
//阻塞线程等待
countDownLatch.await();
Log.e("TAG","主线程执行工作");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2019-12-30 11:19:41.415 30888-30941/com.example.serializationapplication E/TAG: 线程0执行完成
2019-12-30 11:19:41.416 30888-30942/com.example.serializationapplication E/TAG: 线程1执行完成
2019-12-30 11:19:41.416 30888-30943/com.example.serializationapplication E/TAG: 线程2执行完成
2019-12-30 11:19:41.417 30888-30944/com.example.serializationapplication E/TAG: 线程3执行完成
2019-12-30 11:19:41.417 30888-30945/com.example.serializationapplication E/TAG: 线程4执行完成
2019-12-30 11:19:41.417 30888-30888/com.example.serializationapplication E/TAG: 主线程执行工作
1.创建
CountDownLatch
对象,构造函数需要传入int
类型,表示要等待的线程数
2.子线程工作完成调用CountDownLatch
对象的countDown()
方法,CountDownLatch
等待的线程数减1
3.调用CountDownLatch
对象的await()
方法阻塞线程,当所有线程执行完毕才会执行await()
方法后的代码
注意:CountDownLatch更像一个倒计时,某一事件等待所有的线程都执行到一定程度后,事件才会执行
CountDownLatch使用场景:
比如说我们启动一个
APP
,程序需要启动各个服务后才能启动UI
线程
比如说线程A去获取商品单价,线程B去获取商品数量,线程C计算总价格,C则需要等A、B执行完成才能执行。
CyclicBarrier:
CyclicBarrier
的字面意思是可循环使用(Cyclic)
的屏障(Barrier)
。它要做的事情是,让一组线程到达一个点时被阻塞,直到最后一个线程到达这个点,屏障才会开门,所有被屏障拦截的线程才会继续干活。
public class Main6Activity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main6);
//创建CyclicBarrier 对象
final CyclicBarrier barrier =new CyclicBarrier(5);
for(int i = 0; i<5; i++){
final int finalI = i;
new Thread(new Runnable() {
@Override
public void run() {
Log.e("TAG","线程"+ finalI+"执行完成");
try {
//调用await(),表示当前线程到达
barrier.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e("TAG","线程"+ finalI+"执行销毁工作");
}
}).start();
}
}
}
2019-12-30 11:30:04.341 31367-31423/com.example.serializationapplication E/TAG: 线程0执行完成
2019-12-30 11:30:04.344 31367-31425/com.example.serializationapplication E/TAG: 线程1执行完成
2019-12-30 11:30:04.346 31367-31426/com.example.serializationapplication E/TAG: 线程2执行完成
2019-12-30 11:30:04.347 31367-31427/com.example.serializationapplication E/TAG: 线程3执行完成
2019-12-30 11:30:04.351 31367-31428/com.example.serializationapplication E/TAG: 线程4执行完成
2019-12-30 11:30:04.351 31367-31428/com.example.serializationapplication E/TAG: 线程4执行销毁工作
2019-12-30 11:30:04.351 31367-31423/com.example.serializationapplication E/TAG: 线程0执行销毁工作
2019-12-30 11:30:04.352 31367-31425/com.example.serializationapplication E/TAG: 线程1执行销毁工作
2019-12-30 11:30:04.352 31367-31426/com.example.serializationapplication E/TAG: 线程2执行销毁工作
2019-12-30 11:30:04.352 31367-31427/com.example.serializationapplication E/TAG: 线程3执行销毁工作
例如上诉例子,五个线程同时执行,我希望所有的线程都执行完毕后再统一执行销毁动作。因此前面的线程执行完成后就会进入阻塞状态,直到最后的线程执行完成后,所有的线程才会一起执行销毁操作。
CyclicBarrier和CountDownLatch的区别
CountDownLatch是某一事件等待其他事件执行完成才会执行,CyclicBarrier是多个事件都执行到一个点后,各自再执行后续的任务。CountDownLatch强调的是到达某一条件才会去做某件事,CyclicBarrier强调的是到达某一条件大家才能继续执行。
举个例子:公司部门去旅游,导游要等所有人都到达指定地点后才会去买票,这时候其他人还是该上厕所的上厕所、买东西的买东西(强调的是:都到了再去买票)。旅游结束后,大家都要在指定地点等待,等到所有人都到了,各自才可以回家(强调的是:都到了大家才能各自做自己的事)。