JUC中T0级的三大辅助工具类(Semaphore,CountDownLatch,CyclicBarrier)

一、CountDownLatch(减少计数)让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒

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

示例代码:

import java.util.concurrent.CountDownLatch;

/**

 * 解释:8个饭桶陆续离开食堂后扫地僧才可以关灯
 *
 * main主线程必须要等前面8个线程完成全部工作后,自己才能开干
 */
public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(6);
 		//8个在食堂的同学,各自离开食堂的时间不一致
        for (int i = 1; i <= 8; i++){
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t 号饭桶离开食堂");
                countDownLatch.countDown();
            }, String.valueOf(i)).start();
        }
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() + "\t****** 扫地僧关灯走人");

    }

}
二、CyclicBarrier(循环栅栏)可循环(Cyclic)使用的屏障(Barrier)

作用:让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await()方法

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * 
 * 集齐5福瓜分5亿
 */
public class CyclicBarrierDemo {
    private static final int NUMBER = 7;

    public static void main(String[] args) {
        //CyclicBarrier(int parties, Runnable barrierAction)

        CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER, () -> {
            System.out.println("*****集齐5福瓜分5亿");
        });

        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "\t 张福被收集 ");
                    cyclicBarrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }

            }, String.valueOf(i)).start();
        }

    }
}
三、Semaphore(信号量)用于多个共享资源的互斥使和控制并发线程数

3.1 acquire(获取) 当一个线程调用acquire操作时,它要么通过成功获取信号量(信号量减1),要么一直等下去,直到有线程释放信号量,或超时;
3.2 release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。

import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**
 *
 *  厕所占坑
 */
public class SemaphoreDemo {
    public static void main(String[] args) {
    	//设置5个坑位
        Semaphore semaphore = new Semaphore(5);
		//设置9个人拉屎
        for (int i = 1; i <= 9; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + "\t 抢到了坑位");
                    TimeUnit.SECONDS.sleep(new Random().nextInt(5));
                    System.out.println(Thread.currentThread().getName() + "\t------- 离开");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();
                }
            }, String.valueOf(i)).start();
        }
    }
}
发布了148 篇原创文章 · 获赞 70 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/loulanyue_/article/details/105420348