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,则当前线程将被禁用以进行线程调度,并出于休眠状态,直至发生两件事情之一:
- 由于countDown() 方法的调用,计数到达0
- 一些其他线程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();
}
}
}
本文详细介绍了Java并发编程中常用的三个工具类:CountDownLatch、CyclicBarrier和Semaphore。包括它们的基本概念、常用方法及实际应用案例。
1659

被折叠的 条评论
为什么被折叠?



