CountDownLatch(闭锁)
使一个或多个线程等到其他线程执行完成后再执行。
CountDownLatch内部会维护一个初始值为线程数量的计数器,主线程执行await方法,如果计数器大于0,则阻塞等待。当一个线程完成任务后,计数器值减1。当计数器为0时,表示所有的线程已经完成任务,等待的主线程被唤醒继续执行。
构造器中的计数值(count)实际上就是闭锁需要等待的线程数量。这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值。
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 100, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
int count = 10;
final CountDownLatch latch = new CountDownLatch(count);
for (int i = 0; i < count; i++) {
threadPool.execute(new MyRunnable1(latch, i));
}
latch.await();
System.out.println("等待线程被唤醒!");
threadPool.shutdown();
}
}
class MyRunnable1 implements Runnable {
CountDownLatch latch = null;
int i;
public MyRunnable1(CountDownLatch latch, int i) {
this.latch = latch;
this.i = i;
}
@Override
public void run() {
System.out.println("线程" + i +"完成了操作...");
try {
Thread.currentThread();
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
}
}
CyclicBarrier(栅栏)
1.简介
让一组线程到达栅栏时阻塞,直到最后一个线程到达栅栏时,栅栏才会开,所有被阻塞的线程才会继续运行。
2.CyclicBarrier提供2个构造器:
(1) CyclicBarrier(int parties, Runnable barrierAction)
(2) CyclicBarrier(int parties)
注:参数parties指让多少个线程或者任务等待;参数barrierAction为栅栏开放时要执行的内容。
3.应用场景
多线程计算,最后汇总数据
问题:CountDownLatch和CyclicBarrier的区别?
CyclicBarrier可重用的,因为内部计数器可重置;CountDownLatch不可重用,计数器值为0该CountDownLatch就不可再用。
Semaphore(信号量)
用来控制同时访问特定资源的线程数量。比如数据库连接。假如有一个需求,要读取几万个文件的数据,因为都是IO密集型任务,我们可以启动几十个线程并发的读取,但是如果读到内存后,还需要存储到数据库中,而数据库的连接数只有10个,这时我们必须控制只有十个线程同时获取数据库连接保存数据,否则会报错无法获取数据库连接。这个时候,我们就可以使用Semaphore来做流控。
Exchanger
Exchanger可以在两个线程之间交换数据,只能是2个线程,他不支持更多的线程之间互换数据。
当线程A调用Exchange对象的exchange()方法后,他会陷入阻塞状态,直到线程B也调用了exchange()方法,然后以线程安全的方式交换数据,之后线程A和B继续运行。