1、Semaphore(信号量)
信号量为一个资源维护访问许可的线程数量,即同一时间只许限定数量线程可以访问该资源。
如果达到允许的最大允许值,那么线程将不得不等待直到其他拥有许可的线程释放它。
可以简单理解为一个停车场只有若干个停车位,一开始里面都没有车停放,后面慢慢有车进去停放直到所有车位都被占用,这时后面的车辆要等到里面停放的车开走才能进去停车场停放。
应用场景:流量控制,例如数据库的连接数
public class vSamephore {
private static int MAX_COUNT = 5;
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(MAX_COUNT);
for (int i = 0; i < 8; i++) {
new Thread(()->{
try {
semaphore.acquire();
System.out.println("Semaphore permit acquired by "+Thread.currentThread().getName());
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
System.out.println("Semaphore permit getting released by "+Thread.currentThread().getName());
}
},"A"+i).start();
}
}
}
2、CountDownLatch(闭锁)
闭锁可以延迟线程的进度直到其达到终止状态,它允许一个或多个线程等待其他线程完成操作。
CountDownLatch构造函数接受一个int类型的参数N(必须大于0)作为计数器,每当调用countDown()方法时,会将N减1;调用await()方法时会阻塞当前线程直至N减为0.注意:CountDown Latch不能重新初始化或修改其对象内部计数器的值
public class vCountDownLatch {
private static int MAX_COUNT = 3;
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(MAX_COUNT);
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+" calling countdown");
countDownLatch.countDown();
}catch (Exception e) {
e.printStackTrace();
}
}
},"A"+i).start();
}
try {
System.out.println("Waiting for all other threads finish operation");
countDownLatch.await();
System.out.println("All other threads finish operation!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
如果其他工作线程处理的事件花费时间较长或者计数器的值一直都减不到0,可以使用设置超时的await方法——await(long time, TimeUnit unit),如果当前线程等待的时间过后就不会被阻塞。
3、CyclicBarrier(同步屏障)
CyclicBarrier可拆分成Cyclic(可循环)和Barrier(屏障)。
当一组线程到达一个屏障时会被阻塞,直到最后一个线程到达屏障时屏障才会打开,所有被屏障拦截的线程才会继续允许。
可以理解为只有集满7可龙珠才可以召唤神龙,或者运动员全部到场了比赛才可以进行。由Cyclic可得知,CyclicBarrier可以使一定数量的线程反复在屏障位置汇集。而屏障将被重置以便下次使用。
如果await被中断或者超时,那么屏障被认为是打破了,所有线程的await都将被终止并抛出BrokenBarrierException。如果成功的通过屏障,那么await将为每个线程返回一个唯一的到达索引号,我们可以利用这些索引来“选举”产生一个领导线程,并在下一次迭代中由该领导线程执行一些特殊的工作。
public class vCyclicBarrier {
private static int MAX_COUNT = 3;
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(MAX_COUNT);
for (int i = 0; i < 3; i++) {
new Thread(()->{
try{
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"player joining");
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName()+"game start");
}catch (Exception e) {
}
},i+"").start();
}
}
}
简单总结
Semaphore: 管理固定大小的资源池。
CountDownLatch: 一个或多个线程等待一组线程完成操作。
CyclicBarrier: 一组线程相互等待,直到它们到达特定的点。