04并发编程常用辅助类

1CountDownLatch(倒计时门闩)

CountDownLatch 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

闭锁可以延迟线程的进度直到其到达终止状态,闭锁可以用来确保某些活动直到其他活动都完成才继续执行:

  • 确保某个计算在其需要的所有资源都被初始化之后才继续执行;
  • 确保某个服务在其依赖的所有其他服务都已经启动之后才启动;
  • 等待直到某个操作所有参与者都准备就绪再继续执行

CountDownLatch 内部维护了⼀个计数器,只有当计数器==0时,某些线程才会停止阻塞,开始执行。

CountDownLatch 主要有两个方法, countDown() 来让计数器-1, await() 来让线程阻塞。当 count==0 时,阻塞线程自动唤醒。

 案例 班长关门:main线程是班长,6个线程是学生。只有6个线程运行完毕,都离开教室后,main线程班长才会关教室门

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 1; i <= 16; i++) {
            int temp = i;
            new Thread(()->{
                try { TimeUnit.SECONDS.sleep(temp); } catch (InterruptedException e) {e.printStackTrace(); }
                System.out.println("同学离开了教室");
                countDownLatch.countDown();
            }, String.valueOf(i)).start();
        }
        //班长等待关门
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() +"班长最后最后关教室门...");
    }
}

 

 2CyclicBarrier(篱栅)

CyclicBarrier 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。

CountDownLatch 是减,而 CyclicBarrier 是加,理解了 CountDownLatch , CyclicBarrier 就很容易。比如召集7颗⻰珠才能召唤神龙,拼团发货

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

 

去掉sleep方法运行结果为(各个线程不用互相等待)

 

 3Semaphore(信号灯)

 一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。

Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。

CountDownLatch 的问题是不能复用。比如 count=3 ,那么减到0,就不能继续操作了。而Semaphore 可以解决这个问题,比如6辆⻋3个停⻋位,对于 CountDownLatch 只能停3辆车,而Semaphore 可以停6辆⻋,车位空出来后,其它⻋可以占有,这就涉及到了Semaphore.accquire() 和 Semaphore.release() 方法。

/**
 * 在信号量上我们定义两种操作:
 * acquire(获取)当一个线程调用acquire操作时,他要么通过成功获取信号量(信号量减1),要么一直等待下去,直到有线程释放信号量,或超时。
 * release(释放)实际上会将信号量加1,然后唤醒等待的线程。
 *
 * 信号量主要用于两个目的,一个是用于多个共享资源的互斥使用,另一个用于并发线程数的控制
 */
public class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);
        for (int i = 1; i <= 7; i++) {
            final int temp = i;
            new Thread(()->{
                //占有资源
                try {
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName()+"抢到了车位...");
                    try { TimeUnit.SECONDS.sleep(temp); } catch (InterruptedException e) {e.printStackTrace(); }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    System.out.println(Thread.currentThread().getName()+"===释放了车位...");
                    semaphore.release();
                }
            }, String.valueOf(i)).start();
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值