1. CountDownLatch(减数器)
- 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
- 用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置
- 通俗来说:一组线程相当于学生,CountDownLatch相当于门卫,他需要等所有学生都离开以后才关门.
实例:
package com.lee.JUC常用3大辅助类;
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 0; i < 6; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"离开!");
countDownLatch.countDown();//数量-1
},String.valueOf(i)).start();
}
countDownLatch.await(); //等待计数器归零
System.out.println("关门!");
}
}
结果:
2.CyclicBarrier(加数器)
- 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
实例
package com.lee.JUC常用3大辅助类;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(7, ()->{
System.out.println("召集7颗龙珠召唤神龙!");
});
for (int i = 1; i <=7 ; i++) {
final int temp = i;
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"收集到第"+ temp+"颗龙珠!");
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
结果:
3.Semaphore(通行证)
- 一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。
- 通俗来说:假如有4个停车位,但是有10辆车需要停,这个时候就需要排队等待,Semaphore停车位获得和释放的意思。
实例
package com.lee.JUC常用3大辅助类;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(4);//线程数量,相当于停车位
for (int i = 1; i <= 10; i++) {
new Thread(()->{
try {
semaphore.acquire();//得到
System.out.println(Thread.currentThread().getName()+"--->抢到车位");
TimeUnit.SECONDS.sleep(2);//线程休眠2秒
System.out.println(Thread.currentThread().getName()+"--->离开车位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();//释放
}
},String.valueOf(i)).start();
}
}
}
结果:
小结:
- acquire():获得,如果已经满了就等待被释放
- release():释放,会将当前信号量+1,然后唤醒等待的线程