美文网首页
JUC下线程同步类

JUC下线程同步类

作者: 一只小星_ | 来源:发表于2019-08-13 20:01 被阅读0次

这些类为JUC包,他们都起到线程同步作用

Semaphore(信号量)

/**
 * @className: SemaphoreExample1
 * @description: 允许多个线程同时访问(syn,reentrantLock每次只允许访问一个)
 * @author: wbr
 * @date: 2019-08-13 13:25
 */
public class SemaphoreExample1 {
    //请求的数量
    private static final int threadCount = 50;

    public static void main(String[] args) throws InterruptedException {
        创建固定数量的线程池对象,如果数量少了会执行的很慢
        ExecutorService threadPool = Executors.newFixedThreadPool(300);
        一次只能执行的线程数量
        final Semaphore semaphore = new Semaphore(20);

        for (int i=0;i<threadCount;i++){
            final int threadNum = i;
            threadPool.execute(()->{
                try {
                    获得一个许可,如果没有了,就阻塞。里面可以传参数一次性获取多个
                    semaphore.acquire();
                    test(threadNum);
                    释放一个许可,可能会唤醒一些阻塞的线程。释放也可以传参数。
                    semaphore.release();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            });
        }
        threadPool.shutdown();
        System.out.println("finish");
    }


     * 除了acquire()和release(),另一个常用的是tryAcquire(),获取不到就返回false。
     * Semaphore有两种模式:公平和非公平。
     * 公平调用acquire的顺序就是获取许可的顺序,遵循AQS的FIFO。
     * 非公平就是抢占式。
     *
     * Semaphore的构造方法只有两个,默认非公平,都要传入信号量的值:
     *  public Semaphore(int permits) {
     *        sync = new NonfairSync(permits);
     *    }
     *
     *  public Semaphore(int permits, boolean fair) {
     *         sync = fair ? new FairSync(permits) : new NonfairSync(permits);
     *   }
   

    public static void test(int threadNum) throws InterruptedException{
        //模拟请求耗时操作
        Thread.sleep(1000);
        System.out.println("threadNum:"+threadNum);
        //模拟请求耗时操作
        Thread.sleep(1000);
    }

}

在现实场景,Semaphore的实现,比如线程池,你创建的线程池的连接数是有限制的,里面就类似Semaphore实现。
源码深入:https://blog.csdn.net/qq_19431333/article/details/70212663

CountDownLatch (倒计时器)

这个类常常用于等待,等多个线程执行完毕,再让某个线程执行。
CountDownLatch的典型用法就是:
①某一线程在开始运行前等待n个线程执行完毕。将 CountDownLatch 的计数器初始化为n :new CountDownLatch(n),每当一个任务线程执行完毕,就将计数器减1 countdownlatch.countDown(),当计数器的值变为0时,在CountDownLatch上 await() 的线程就会被唤醒。一个典型应用场景就是启动一个服务时,主线程需要等待多个组件加载完毕,之后再继续执行。

public class CountDownLatchExample1 {
    //请求的数量
    private static final int threadCount = 550;

    public static void main(String[] args) throws InterruptedException{
        ExecutorService executorService = Executors.newFixedThreadPool(300);
        final CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        for (int i=0;i<threadCount;i++){
            final  int threadNum = i;
            executorService.execute(() ->{
                try {
                    test(threadNum);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }finally {
                    //表示一个请求已完成
                    countDownLatch.countDown();
                }

            });
        }
        //await之后的都要等待,等countDownLatch减到0,await之后的才能执行
        countDownLatch.await();
        executorService.shutdown();

    }
    public static void test(int threadCount)  throws InterruptedException{
        //模拟请求的耗时操作
        Thread.sleep(1000);
        System.out.println("threadCount:"+threadCount);
        Thread.sleep(1000);
    }

}

CountDownLatch是一次性的,计数器的值只能在构造方法中初始化一次,之后没有任何机制再次对其设置值,当CountDownLatch使用完毕后,它不能再次被使用。

CyclicBarrier(循环栅栏)

CyclicBarrier 和 CountDownLatch 非常类似,它也可以实现线程间的技术等待,CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。


image.png
public class CyclicBarrierExample3 {
    // 请求的数量
    private static final int threadCount = 550;
    // 需要同步的线程数量
    private static final CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> {
        System.out.println("------当线程数达到之后,优先执行------");
    });

    public static void main(String[] args) throws InterruptedException {
        // 创建线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(10);

        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            Thread.sleep(1000);
            threadPool.execute(() -> {
                try {
                    test(threadNum);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            });
        }
        threadPool.shutdown();
    }

    public static void test(int threadnum) throws InterruptedException, BrokenBarrierException {
        System.out.println("threadnum:" + threadnum + "is ready");
        cyclicBarrier.await();
        System.out.println("threadnum:" + threadnum + "is finish");
    }

}

相关文章

网友评论

      本文标题:JUC下线程同步类

      本文链接:https://www.haomeiwen.com/subject/mxbvjctx.html