JUC中提供了三种常用的辅助类,通过这些辅助类可以很好的解决线程数量过多时Lock锁的频繁操作。这三种辅助类为:
• CountDownLatch: 减少计数
• CyclicBarrier: 循环栅栏
• Semaphore: 信号灯

1. CountDownLatch 减少计数

CountDownLatch类可以设置一个计数器,然后通过countDown()方法来进行减1的操作,使用await方法等待计数器不大于0,然后继续执行await方法之后的语句。

• CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞
• 其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞)
• 当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行.

  1. package juc.CB;
  2. import java.util.concurrent.BrokenBarrierException;
  3. import java.util.concurrent.CyclicBarrier;
  4. /**
  5. * @Author Rock Wang
  6. * @Time 2021/11/11
  7. */
  8. public class CyclicBarrierDemo {
  9. private static final int NUM = 7;
  10. //找到七龙珠,召唤神龙
  11. public static void main(String[] args) {
  12. CyclicBarrier cyclicBarrier = new CyclicBarrier(NUM, () -> {
  13. System.out.println("神龙: 叫我啥事?");
  14. });
  15. for (int i = 0; i < 7; i++) {
  16. new Thread(() -> {
  17. try {
  18. System.out.println("找到" + Thread.currentThread().getName() + "号龙珠");
  19. cyclicBarrier.await();
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. } catch (BrokenBarrierException e) {
  23. e.printStackTrace();
  24. }
  25. }, i + "").start();
  26. }
  27. }
  28. }

2. CyclicBarrier循环栅栏

CyclicBarrier看英文单词可以看出大概就是循环阻塞的意思,在使用中CyclicBarrier的构造方法第一个参数是目标障碍数,每次执行CyclicBarrier一次障碍数会加一,如果达到了目标障碍数,才会执行cyclicBarrier.await()之后的语句。可以将CyclicBarrier理解为加1操作.

  1. package juc.CB;
  2. import java.util.concurrent.BrokenBarrierException;
  3. import java.util.concurrent.CyclicBarrier;
  4. /**
  5. * @Author Rock Wang
  6. * @Time 2021/11/11
  7. */
  8. public class CyclicBarrierDemo {
  9. private static final int NUM = 7;
  10. //找到七龙珠,召唤神龙
  11. public static void main(String[] args) {
  12. CyclicBarrier cyclicBarrier = new CyclicBarrier(NUM, () -> {
  13. System.out.println("神龙: 叫我啥事?");
  14. });
  15. for (int i = 0; i < 7; i++) {
  16. new Thread(() -> {
  17. try {
  18. System.out.println("找到" + Thread.currentThread().getName() + "号龙珠");
  19. cyclicBarrier.await();
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. } catch (BrokenBarrierException e) {
  23. e.printStackTrace();
  24. }
  25. }, i + "").start();
  26. }
  27. }
  28. }

3. Semaphore信号量

Semaphore的构造方法中传入的第一个参数是最大信号量(可以看成最大线程池),每个信号量初始化为一个最多只能分发一个许可证。
使用acquire方法获得许可证,release方法释放许可。

  1. package juc.Semapohre;
  2. import java.util.Random;
  3. import java.util.concurrent.Semaphore;
  4. import java.util.concurrent.TimeUnit;
  5. /**
  6. * @Author Rock Wang
  7. * @Time 2021/11/11
  8. */
  9. public class SemaphoreDemo {
  10. public static void main(String[] args) {
  11. //声明有三个许可
  12. Semaphore semaphore = new Semaphore(3);
  13. //六个车
  14. for (int i = 0; i < 7; i++) {
  15. new Thread(() -> {
  16. try {
  17. System.out.println(Thread.currentThread().getName() + " 准备停车");
  18. semaphore.acquire();
  19. System.out.println(Thread.currentThread().getName() + " 停车成功!");
  20. //随机停五秒以内
  21. TimeUnit.SECONDS.sleep(new Random().nextInt(10));
  22. System.out.println(Thread.currentThread().getName() + " 离开了车位");
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. } finally {
  26. semaphore.release();
  27. }
  28. },"鄂"+i).start();
  29. }
  30. }
  31. }