JUC中提供了三种常用的辅助类,通过这些辅助类可以很好的解决线程数量过多时Lock锁的频繁操作。这三种辅助类为:
• CountDownLatch: 减少计数
• CyclicBarrier: 循环栅栏
• Semaphore: 信号灯
1. CountDownLatch 减少计数
CountDownLatch类可以设置一个计数器,然后通过countDown()方法来进行减1的操作,使用await方法等待计数器不大于0,然后继续执行await方法之后的语句。
• CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞
• 其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞)
• 当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行.
package juc.CB;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;/*** @Author Rock Wang* @Time 2021/11/11*/public class CyclicBarrierDemo {private static final int NUM = 7;//找到七龙珠,召唤神龙public static void main(String[] args) {CyclicBarrier cyclicBarrier = new CyclicBarrier(NUM, () -> {System.out.println("神龙: 叫我啥事?");});for (int i = 0; i < 7; i++) {new Thread(() -> {try {System.out.println("找到" + Thread.currentThread().getName() + "号龙珠");cyclicBarrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}, i + "").start();}}}
2. CyclicBarrier循环栅栏
CyclicBarrier看英文单词可以看出大概就是循环阻塞的意思,在使用中CyclicBarrier的构造方法第一个参数是目标障碍数,每次执行CyclicBarrier一次障碍数会加一,如果达到了目标障碍数,才会执行cyclicBarrier.await()之后的语句。可以将CyclicBarrier理解为加1操作.
package juc.CB;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;/*** @Author Rock Wang* @Time 2021/11/11*/public class CyclicBarrierDemo {private static final int NUM = 7;//找到七龙珠,召唤神龙public static void main(String[] args) {CyclicBarrier cyclicBarrier = new CyclicBarrier(NUM, () -> {System.out.println("神龙: 叫我啥事?");});for (int i = 0; i < 7; i++) {new Thread(() -> {try {System.out.println("找到" + Thread.currentThread().getName() + "号龙珠");cyclicBarrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}, i + "").start();}}}
3. Semaphore信号量
Semaphore的构造方法中传入的第一个参数是最大信号量(可以看成最大线程池),每个信号量初始化为一个最多只能分发一个许可证。
使用acquire方法获得许可证,release方法释放许可。
package juc.Semapohre;import java.util.Random;import java.util.concurrent.Semaphore;import java.util.concurrent.TimeUnit;/*** @Author Rock Wang* @Time 2021/11/11*/public class SemaphoreDemo {public static void main(String[] args) {//声明有三个许可Semaphore semaphore = new Semaphore(3);//六个车for (int i = 0; i < 7; i++) {new Thread(() -> {try {System.out.println(Thread.currentThread().getName() + " 准备停车");semaphore.acquire();System.out.println(Thread.currentThread().getName() + " 停车成功!");//随机停五秒以内TimeUnit.SECONDS.sleep(new Random().nextInt(10));System.out.println(Thread.currentThread().getName() + " 离开了车位");} catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release();}},"鄂"+i).start();}}}
