CountDownLatch
CountDownLatch类可以设置一个计数器,然后通过countDown方法来进行减1的操作,使用await方法等待计数器不大于0,然后继续执行await方法之后的语句。
示例用法:
public class test_01 {
public static void main(String[] args) throws InterruptedException {
// 计数器值是6
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <= 6; i++) {
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" Go Out!");
countDownLatch.countDown(); // 计数器减1
},String.valueOf(i)).start();
}
countDownLatch.await(); // 等待计数器不大于0 再继续执行否则一直阻塞
System.out.println("计数器已经归0啦!");
}
}
CyclicBarrier
CyclicBarrier看英文单词可以看出大概就是循环阻塞的意思,在使用中CyclicBarrier的构造方法第一个参数是目标障碍数,每次执行CyclicBarrier一次障碍数会加一,如果达到了目标障碍数,才会执行cyclicBarrier.await()之后的语句。和CountDownLatch相反,可以将CyclicBarrier理解为加1操作
示例用法:集齐7颗龙珠召唤神龙
public class CyclicBarrierDemo {
public static void main(String[] args) {
// 召唤龙珠的线程
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
System.out.println("召唤神龙成功!");
});
for (int i = 1; i <=7 ; i++) {
final int temp = i;
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"收集"+temp+"星球");
try {
cyclicBarrier.await(); // 等待
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}
Semaphore
Semaphore的构造方法中传入的第一个参数是最大信号量(可以看成最大线程池),每个信号量初始化为一个最多只能分发一个许可证。使用acquire方法获得许可证,release方法释放许可。Semaphore默认使用的非公平锁,在信号量都被使用的时候会阻塞等待线程释放信号量(默认不会出现抢占情况)。
示例用法:抢车位!6个车,3个停车位
public class SemaphoreDemo {
public static void main(String[] args) {
ArrayList<String> car = new ArrayList<>();
car.add("宝马");
car.add("奔驰");
car.add("奥迪");
car.add("兰博基尼");
car.add("玛莎拉蒂");
car.add("劳斯莱斯");
// 线程数量:停车位! 限流!
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i <car.size() ; i++) {
new Thread(()->{
// acquire() 得到
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(); // release() 释放
}
},car.get(i)).start();
}
}
}