1、减少计数CountDownLatch

案例演示:班长等待班上的6位同学离开后关上门。

此种情况会出现错误…….

  1. public class CountDownLatchDemo {
  2. public static void main(String[] args) {
  3. for(int i=1;i<=6;i++){
  4. new Thread(()->{
  5. System.out.println(Thread.currentThread().getName()+"号同学离开了教室");
  6. },String.valueOf(i)).start();
  7. }
  8. System.out.println(Thread.currentThread().getName()+"班长关门了");
  9. }
  10. }
  1. 1号同学离开了教室
  2. 3号同学离开了教室
  3. main班长关门了
  4. 2号同学离开了教室
  5. 4号同学离开了教室
  6. 5号同学离开了教室
  7. 6号同学离开了教室

解决方案:使用CountDownLatch

  1. public class CountDownLatchDemo {
  2. public static void main(String[] args) throws InterruptedException {
  3. //创建CountDownLatch对象,设置初始值
  4. CountDownLatch countDownLatch=new CountDownLatch(6);
  5. //6个随机线程代表6个随机离开的学生
  6. for(int i=1;i<=6;i++){
  7. new Thread(()->{
  8. System.out.println(Thread.currentThread().getName()+"号同学离开了教室");
  9. //每离开一位同学计数器便减1
  10. countDownLatch.countDown();
  11. },String.valueOf(i)).start();
  12. }
  13. //当计数器的值不为0时,则main线程等待
  14. countDownLatch.await();
  15. System.out.println(Thread.currentThread().getName()+"班长关门了");
  16. }
  17. }

2、循环栅栏CyclicBarrier

案例:集齐七龙珠召唤神龙一样的道理,给线程设置好目标,当线程的数量达到之后,即会执行成功需要进行的操作。

  1. public class CyclicBarrierDemo {
  2. private static final int NUMBER=7;
  3. public static void main(String[] args) {
  4. //创建CyclicBarrier对象,设置数量以及目标达到后需要进行的操作
  5. CyclicBarrier cyclicBarrier= new CyclicBarrier(NUMBER,()->{
  6. System.out.println("七龙珠召唤神龙");
  7. });
  8. for(int i=1;i<=7;i++){
  9. new Thread(()->{
  10. try {
  11. System.out.println(Thread.currentThread().getName()+"颗龙珠");
  12. //未收集完则等待
  13. cyclicBarrier.await();
  14. } catch (InterruptedException e) {
  15. e.printStackTrace();
  16. } catch (BrokenBarrierException e) {
  17. e.printStackTrace();
  18. }
  19. },String.valueOf(i)).start();
  20. }
  21. }
  22. }

3、信号灯Semaphore

案例:6个线程去抢占车位,并且在占用车位一定的时间后再离开。

  1. public class SemaphoreDemo {
  2. public static void main(String[] args) {
  3. Semaphore semaphore = new Semaphore(3);
  4. for (int i = 1; i <= 6; i++) {
  5. new Thread(() -> {
  6. try {
  7. //抢占车位
  8. semaphore.acquire();
  9. System.out.println(Thread.currentThread().getName() + ":抢占到车位");
  10. //随机设置占用车位的时间1-5秒
  11. TimeUnit.SECONDS.sleep(new Random().nextInt(5));
  12. System.out.println(Thread.currentThread().getName() + ":离开了车位");
  13. } catch (InterruptedException e) {
  14. e.printStackTrace();
  15. } finally {
  16. //释放车位
  17. semaphore.release();
  18. }
  19. }, String.valueOf(i)).start();
  20. }
  21. }
  22. }