1、CountDownLatch(计数器锁)
1.1、概述
CountDownLatch类可以设置一个计数器,然后通过countDown方法来进行减1的操作,使用await方法等待计数器不大于0,然后继续执行await方法之后的语句。
1.2、注意事项
(1)CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞。
(2)其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞)。
(3)当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行。
1.3、示例
六个同学陆续离开教室后,班长才可以锁门。
(1)先这样写
public class CountDownLatchDemo {
public static void main(String[] args) {
for (int i = 1; i <=6 ; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"号同学走了!");
},String.valueOf(i)).start();
}
System.out.println(Thread.currentThread().getName()+"班长锁门了");
}
}
显然没达到效果。
(2)然后加上CountDownLatch
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
//定义一个CountDownLatch,并设置一个初始值为6
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <=6 ; i++) {
new Thread(()->{
//计数器减1
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName()+"号同学走了!");
},String.valueOf(i)).start();
}
//等待/阻塞
countDownLatch.await();
System.out.println(Thread.currentThread().getName()+"班长锁门了");
}
}
2、CyclicBarrier(循环栅栏)
2.1、概述
CyclicBarrier看英文单词可以看出大概就是循环阻塞的意思,在使用中CyclicBarrier的构造方法第一个参数是目标障碍数,每次执行CyclicBarrier一次障碍数会加一,如果达到了目标障碍数,才会执行cyclicBarrier.await0之后的语句。可以将CyclicBarrier理解为加1操作。
2.2、实例
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
//集齐7颗龙珠,召唤神龙
public static final int NUMBER=7;
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER, () -> {
System.out.println(Thread.currentThread().getName() + "最终集齐7龙珠,召唤神龙!");
});
//集齐7可龙珠的过程
for (int i = 1; i <=7 ; i++) {
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName() + "号龙珠被拿到!");
//等待
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
3、Semaphore(信号量)
3.1、概述
Semaphore的构造方法中传入的第一个参数是最大信号量 (可以看成最大线
程池) ,每个信号量初始化为一个最多只能分发一个许可证。 使用acquire方
法获得许可证, release方法释放许可。
3.2、示例
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphoreDemo {
//场景:6辆汽车抢三个停车位
public static void main(String[] args) {
//创建Semaphore,设置许可数量
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(new Random().nextInt(4));
System.out.println(Thread.currentThread().getName()+"-----离开了车位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//释放许可
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}