• CountDownLatch、CyclicBarrier和Semaphore基本原理和使用


    一、CountDownLatch

    CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。
    比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。

      CountDownLatch让一些线程阻塞知道另一些线程完成一系列操作后才被唤醒,CountDownLatch主要有两个方法,当一份或多个线程调用await方法时,调用线程会被阻塞。其他线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞),当计数器的值变为0时,因调用await方法被阻塞的线程会被唤醒,继续执行。

    public class CountDownLatchDemo {
    
        public static void main(String[] args) {
            CountDownLatch countDownLatch = new CountDownLatch(6);
            for (int i = 0; i < 6; i++) {
                new Thread(()->{
                    System.out.println("当前线程任务结束 : " + Thread.currentThread().getName());
                    countDownLatch.countDown();
                }, String.valueOf(i)).start();
            }
    
            try {
                // 等待其他线程执行完再执行
                countDownLatch.await();
                System.out.println("************全部执行结束***********");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
        }
    }

    输出结果:

    当前线程任务结束 : 0
    当前线程任务结束 : 2
    当前线程任务结束 : 3
    当前线程任务结束 : 1
    当前线程任务结束 : 4
    当前线程任务结束 : 5
    ************全部执行结束***********

    二、CyclicBarrier

    CyclicBarrier的字面意思是可循环(Cyclic)使用的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await()方法,当调用await()方法之后,线程就处于barrier了。

    代码测试:收集七颗龙珠,召唤神龙。

    public class CyclicBarrierDemo {
    
        public static void main(String[] args) {
            CyclicBarrier barrier = new CyclicBarrier(7,
                    () -> {
                        System.out.println("**********召唤神龙**********");
                    });
            for (int i = 1; i <= 7; i++){
                new Thread(()->{
                   System.out.println("第" + Thread.currentThread().getName() + " 颗龙珠被收集");
                    try {
                        barrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }, String.valueOf(i)).start();
            }
        }
    }

    输出结果:

    第1 颗龙珠被收集
    第7 颗龙珠被收集
    第6 颗龙珠被收集
    第5 颗龙珠被收集
    第4 颗龙珠被收集
    第3 颗龙珠被收集
    第2 颗龙珠被收集
    **********召唤神龙**********

    三、Semaphore

    Semaphore翻译成字面意思为信号量,Semaphore可以控同时访问的线程个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。

    信号量主要用于两个目的,一个是用于多个共享资源的互斥使用,另一个是用于并发线程数的控制

    代码实现小案例:6辆汽车抢夺3个停车位。

    public class SemaphoreDemo {
    
        public static void main(String[] args) {
            Semaphore semaphore = new Semaphore(3);
    
            for (int i = 1; i <= 6; i++){
                new Thread(()->{
                    try {
                        // 获取资源
                        semaphore.acquire();
                        System.out.println(Thread.currentThread().getName() + "号车获得停车位");
                        TimeUnit.SECONDS.sleep(3);
                        System.out.println(Thread.currentThread().getName() + "号车停车3秒离开停车位");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        // 释放资源
                        semaphore.release();
                    }
    
                },String.valueOf(i)).start();
            }
        }
    }

    输出结果:

    1号车获得停车位
    3号车获得停车位
    4号车获得停车位
    4号车停车3秒离开停车位
    3号车停车3秒离开停车位
    5号车获得停车位
    1号车停车3秒离开停车位
    6号车获得停车位
    2号车获得停车位
    6号车停车3秒离开停车位
    5号车停车3秒离开停车位
    2号车停车3秒离开停车位
    
    Process finished with exit code 0
  • 相关阅读:
    Java 将File转换为MultipartFile类型
    JAVA中实现根据文件路径下载文件
    Java中类似单元格之间的计算公式解析,如A1+B3-B4
    Java JPA通过hql语句查询数据
    mysql与oracle 表字段定义比较
    Java时间日期DateUtil
    fetch缓存问题
    Vue中watch的简单应用
    关于跨域和如何解决跨域问题的小结
    Google play 一直等待下载?解决方案如此简单!
  • 原文地址:https://www.cnblogs.com/ch-forever/p/10782270.html
Copyright © 2020-2023  润新知