JUC并发编程——常用的辅助工具类

本文详细介绍了Java并发编程中常用的三个工具类:CountDownLatch、CyclicBarrier和Semaphore。包括它们的基本概念、常用方法及实际应用案例。

JUC并发编程——常用的工具类

1、CountDownLatch

CountDownLatch 简介

CountDownLatch 是JUC下面的同步工具类,能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成一些任务,然后在CountDownLatch上等待的线程就可以恢复执行接下来的任务。

一个CountDownLatch为一个计数的CountDownLatch用作一个简单的开/关锁存器,或者门:所有线程调用await`在门口等待,直到被调用countDown()的线程打开。 一个CountDownLatch初始化N可以用来做一个线程等待,直到N个线程完成某项操作,或某些动作已经完成N次。

CountDownLatch 常用方法

1、构造方法:CountDownLatch(int count)

给定计数值初始化 CountDownLatch。

参数 :count为计数值

2、countDown()

减少锁存器的计数,如果计数到达0,释放所有等待线程。

如果当前计数大于0,则它将递减,如果新计数为0,则所有等待的线程都将被重新启用以进行线程的调度。

3、await()

让当前线程等待锁存器计数为0,除非线程是 interrupted(被中断的)。

如果当前计数为0,则此方法立即返回。

如果当前计数大于0,则当前线程将被禁用以进行线程调度,并出于休眠状态,直至发生两件事情之一:

  1. 由于countDown() 方法的调用,计数到达0
  2. 一些其他线程interrupts(中断)当前线程

4、await(long timeout,TimeUnit unit)

使当前线程等待直到闩锁倒计时为零,除非线程被中断,或者指定的等待时间已过。

如果当前计数为零,则此方法立即返回值为true 。

如果当前计数大于零,则当前线程出于线程调度目的而被禁用并处于休眠状态,直到发生以下三种情况之一:

由于调用了countDown方法,计数达到零;

或者其他一些线程中断当前线程;

或者指定的等待时间已过。

如果计数达到零,则该方法返回值为true 。

如果当前线程:在进入此方法时设置其中断状态; 或者等待时被打断,然后抛出InterruptedException并清除当前线程的中断状态。

如果指定的等待时间过去,则返回值false 。 如果时间小于或等于零,则该方法根本不会等待。

参数:

timeout 等待的最长时间

unit – timeout 参数的时间单位

返回:如果计数达到零,则为true如果在计数达到零之前经过了等待时间,则为false

抛出:InterruptedException – 如果当前线程在等待时被中断

CountDownLatch 使用案例

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        //初始化一个计数值为5的锁存器
        CountDownLatch countDownLatch = new CountDownLatch(5);

        for (int i = 0; i < 5; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"Go out");
                countDownLatch.countDown();//锁存器的计数值--
            },String.valueOf(i)).start();
        }
        countDownLatch.await();//让当前线程等待,直到锁存器计数为0,再向下执行
        System.out.println("等待线程开始被调用");

    }
}

2、CyclicBarrier

CyclicBarrier 简介

CyclicBarrier 是一种同步辅助工具类,它允许一组线程全部等待彼此到达公共屏障点。 CyclicBarriers 在涉及固定大小的线程组的程序中很有用,这些线程必须偶尔相互等待。 屏障是循环的,因为它可以在等待线程被释放后重新使用。

CyclicBarrier支持可选的Runnable命令,该命令在每个屏障点运行一次,在一组线程中的最后一个线程到达之后,但在任何线程被释放之前。 此屏障操作对于在任何一方继续之前更新共享状态很有用。

利用CyclicBarrier 类可以实现一组线程相互等待,当所有线程都到达某个屏障点后再进行后续的操作。

CyclicBarrier 常用方法

1、构造方法:

CyclicBarrier(int parties, Runnable barrierAction):创建一个新的CyclicBarrier ,它将在给定数量的参与方(线程)等待时触发,

并在屏障触发时执行给定的屏障操作,由进入屏障的最后一个线程执行。

参数:parties 在障碍被触发之前必须调用await的线程数

​ barrierAction 障碍物被触发时执行的命令,如果没有动作则为null

CyclicBarrier(int parties):创建一个新的CyclicBarrier ,当给定数量的参与方(线程)正在等待它时,它将跳闸,并且当屏障跳闸

时不执行预定义的操作。

2、await()

等待所有线程都调用了await ,线程调用 await() 表示自己已经到达屏障,

如果当前线程不是最后一个到达的线程,那么它会出于线程调度目的而被禁用并处于休眠状态,直到发生以下情况之一:

  • 最后一个线程到达;

  • 或者其他一些线程中断当前线程;

  • 或者其他一些线程中断了其他等待线程之一;

  • 或者其他一些线程在等待屏障时超时;

  • 或者其他一些线程在此屏障上调用reset()(将屏障重置为初始状态) 。

返回:当前线程的到达索引,其中 index getParties() ,- 1表示第一个到达,零表示最后一个到达

3、await(long timeout, TimeUnit unit)

等待所有参与方都在此屏障上调用了await ,或者指定的等待时间已过。

如果当前线程不是最后一个到达的线程,那么它会出于线程调度目的而被禁用并处于休眠状态,直到发生以下情况之一:

  • 最后一个线程到达;

  • 或者指定的超时时间已过;

  • 或者其他一些线程中断当前线程;

  • 或者其他一些线程中断了其他等待线程之一;

  • 或者其他一些线程在等待屏障时超时;

  • 或者其他一些线程在此屏障上调用 reset()(将屏障重置为初始状态)。

CyclicBarrier 使用案例

public class CyclicBarrierDemo {
    public static void main(String[] args) {

        //创建 CyclicBarrier
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
            System.out.println("集齐七颗龙珠,召唤神龙!");
        });
        for (int i = 0; i < 7; i++) {
            final int temp = i;
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"收集了"+temp+"个龙珠");
                try {
                    cyclicBarrier.await();//线程调用await方法
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

3、Semaphore

Semaphore 简介

Semaphore 通常叫它信号量, 可以用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用资源。

信号量通常用于限制线程数(限流),而不是访问某些(物理或逻辑)资源。

Semaphore 常用方法

1、构造方法

Semaphore(int permits):创建具有给定数量的许可和非公平公平设置的信号量。

Semaphore(int permits, boolean fair):使用给定的许可数量和给定的公平设置创建一个信号量 。

2、acquire()

当前线程从这个信号量中获取一个许可,在提供一个许可前一直将该线程阻塞,否则线程被中断。

获得许可证(如果有)并立即返回,将可用许可证的数量减少一个。

如果没有可用的许可,则当前线程将出于线程调度目的而被禁用并处于休眠状态,直到发生以下两种情况之一:

  • 其他一些线程调用该信号量的release方法,当前线程接下来将被分配一个许可;

  • 或者一些其他线程中断当前线程。

3、release()

释放许可证,将可用许可证的数量增加一个。如果有任何线程试图获得许可,则选择一个线程并给予刚刚释放的许可。

Semaphore 使用案例

这是一个使用信号量来控制对一个资源的访问的类:

public class SemaphoreDemo {
    public static void main(String[] args) {
        //创建具有5个许可和非公平公平设置的信号量
        Semaphore semaphore = new Semaphore(5);

        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                try {
                    semaphore.acquire();//获取许可证
                    System.out.println(Thread.currentThread().getName()+"线程开始执行");
                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(Thread.currentThread().getName()+"线程执行结束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release(); //释放许可证
                }
            },String.valueOf(i)).start();
        }
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万里顾—程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值