JUC中T0级的三大辅助工具类:
CountDownLatch(减少计数)
CyclicBarrier(循环栅栏)
Semaphore(信号量)
一、CountDownLatch(减少计数)让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒
主要有两个方法,
1.1、当一个或多个线程调用await方法时,这些线程会阻塞,其它线程调用countDown方法会将计数器减一(调用countDown方法的线程不会阻塞);
1.2、当计数器的值变为0时,await方法阻塞的线程会被唤醒,继续执行
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(5);for (int i = 1; i < 6; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName());countDownLatch.countDown(); //数量减1},String.valueOf(i)).start();}//await() 等待计数器归零,全部都跑完了再进下面的操作countDownLatch.await();System.out.println("Close");}
}
二、CyclicBarrier(循环栅栏)可循环(Cyclic)使用的屏障(Barrier)
作用:让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await()方法
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(5,()->{
System.out.println("拼图已完成,你真棒!");});for (int i = 1; i < 6; i++) {
final int temp = i;new Thread(()->{
System.out.println("拼了"+temp+"个图");try {
cyclicBarrier.await(); //等待。 当拼完第五张图的时候,执行构造中Runnable} catch (InterruptedException e) {
e.printStackTrace();} catch (BrokenBarrierException e) {
e.printStackTrace();}}).start();}}
}
CyclicBarrier 与 CountDownLatch 区别
2.1、CountDownLatch 是一次性的,CyclicBarrier 是可循环利用的
2.2、CountDownLatch 参与的线程的职责是不一样的,有的在倒计时,有的在等待倒计时结束。CyclicBarrier 参与的线程职责是一样的。
三、Semaphore(信号量)用于多个共享资源的互斥使和控制并发线程数
3.1 acquire(获取) 当一个线程调用acquire操作时,它要么通过成功获取信号量(信号量减1),要么一直等下去,直到有线程释放信号量,或超时;
3.2 release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。
public class SemahporeDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3); //线程的数量//模拟有五辆车for (int i = 1; i < 6; i++) {
new Thread(()->{
try {
semaphore.acquire(); //获得 获取到一个位置System.out.println(Thread.currentThread().getName()+"抢到了车位");TimeUnit.SECONDS.sleep(2);System.out.println(Thread.currentThread().getName()+"离开了车位");} catch (InterruptedException e) {
e.printStackTrace();}finally {
semaphore.release(); //释放 , 离开}},String.valueOf(i)).start();}}
}
如果线程数满了就要等待被释放,然后等待的线程在得到释放的资源的时候去获取到位置。
在释放之后会唤醒其他线程去获取资源。