今天给大家介绍的是Java的同步工具类,CountDownLatch和CyclicBarrier。
首先讲讲CountDownLatch,中文名叫线程计数器,在jdk1.5时引入的,这个功能是初始化可以设置一个数量,每个线程执行后latch可以减1,当latch减为0时,才不会阻塞。
惯用的模式:
CountDownLatch latch = new CountDownLatch(nums);
Thread th1 = new Thread(()->{
//业务操作完成后
lathch.countDown()//-1
});
th1.start();
Thread th2 = new Thread(()->{
//业务操作完成后
lathch.countDown()//-1
});
th2.start();
latch.await(); //如果这个时候为被减为0所有线程在这阻塞,直至0为止,再释放。
//后续的操作
这个计数就是为了解决,因为在某些场景下join方法操作不了不能使多个线程等待,(比如线程池里的线程等待操作,不能通过join操作来等待再执行,于是有这个工具类),更加方便线程池线程之间的协作工作。
举几个例子:
1.多个线程同时下载大文件,等待所有线程下载完成,主线程再合并或者做其他操作。
2.或者初始化资源时,等待初始化线程初始化资源工作,等待初始线程工作完成之后,再来启动主线程。
CyclicBarrier
CyclicBarrier中文名叫回环栅栏,它也是一种线程同步工具类,但是它和CountDownLatch相比,它有独特的功能。如:自动重置计数,回调功能。
使用模式:
final CyclicBarrier barrier =
new CyclicBarrier(2, ()->{
executor.execute(()->check());
});
void check(){
//cyclicBarrier回调函数
}
void done(){
Thread th1 = new Thread(()->{
//业务操作完成后
barrier .await()//-1
});
th1.start();
Thread th2 = new Thread(()->{
//业务操作完成后
barrier .await()//-1
});
}
CyclicBarrier 体现在一组线程间的同步策略,在barrier.await()后,内部计数器减1,如果当前线程await()后,内部计数器不为0,即当前线程阻塞,等待其他线程不断await(),直至内部计数器减为0后,可以执行一个barrier的回调方法(唤醒其他线程),同时,重新将内部计数器重置。再将当前一组线程重新唤醒。
总结:CountDownLatch主要解决一个线程等待多个线程的场景,而CyclicBarrier是一组线程之间互相等待,但是,CountDownLatch的计数器不能循环利用,一旦计数器到0后,后续的线程可以直接通过await(),但是CyclicBarrier得计数器可以循环利用的,具备自动重置功能,还能设置回调函数。