1 CountDownLatch
- (1)countDownLatch等待指定数量线程结束后,进行下一步;
- (2)countDownLatch构造函数初始化一个volatile变量,countDown()方法,使用了CAS,和AutomicInteger的增减方法相同;
- (3)await方法阻塞当前线程,直到getCount值为0,如果不调用countDown方法,getCount的值部位0,那么会一直阻塞。
import java.util.Random;
import java.util.concurrent.CountDownLatch;
// CountDownLatchDemo,运送完5车火石,启动行星发动机
class CountDownLatchDemo
{
static final int count = 5;
static CountDownLatch countDownLatch = new CountDownLatch(count);
public static void main(String[] args)
{
for(int i = 0; i < count; i++){
new Thread(new Runnable()
{
@Override
public void run()
{
try{
int t = new Random().nextInt(5000);
Thread.sleep(t);
System.out.println("耗费" + t + "ms" + "运送完第" + countDownLatch.getCount() + "车火石");
countDownLatch.countDown();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}).start();
}
try
{
countDownLatch.await();
System.out.println("当前阻塞线程数: " + countDownLatch.getCount());
System.out.println("运送完毕,启动行星发动机");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
运行结果:
耗费1329ms运送完第5车火石
耗费1775ms运送完第4车火石
耗费2546ms运送完第3车火石
耗费4365ms运送完第2车火石
耗费4531ms运送完第1车火石
当前阻塞线程数: 0
运送完毕,启动行星发动机
Process finished with exit code 0
2 CyclicBarrier
CyclicBarrier也能够实现等待指定数量结束后进行下一步,可以设置屏障,实现诸如:多线程并发–>单线程–>多线程并发,这样的流程。
- (1)CyclicBarrier的构造函数中,parties表示屏障中最大阻塞的线程数量,Runnable表示下一步操作。
- (2)CyclicBarrier的await方法将当前线程添加到等待队列中,直到等待队列线程数量达到规定值,才开始进行下一步。
- (3)getNumberWaiting()方法能够查看当前队列中阻塞的进程数,reset()方法能够清空阻塞的进程数,从头计数,阻塞的线程会抛出broken异常。
- (4)CyclicBarrier不会阻塞主线程
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
/**
* 循环屏障demo,集齐10位驾驶员,驾驶员到齐后,运送5车火石,启动行星发动机
*/
public class CyclicBarrierDemo
{
final static int driver = 10;
final static int fireStone = 5;
public static void main(String[] args)
{
CyclicBarrierDemo cbd = new CyclicBarrierDemo();
cbd.barrier1(driver);
System.out.println("这是主线程");
}
//屏障点1,集齐10位驾驶员
public void barrier1(int num){
CyclicBarrier cyclicBarrier1 = new CyclicBarrier(num, new Runnable()
{
@Override
public void run()
{
System.out.println("驾驶员集齐,开始运送火石");
barrier2(fireStone);
}
});
for(int i = 0; i < num; i++){
new Thread(new Runnable()
{
@Override
public void run()
{
try{
int t = new Random().nextInt(3000);
Thread.sleep(t);
System.out.println("驾驶员" +cyclicBarrier1.getNumberWaiting() + "就位");
cyclicBarrier1.await();
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
}
}
//屏障点2,运送5车火石
public void barrier2(int num){
CyclicBarrier cyclicBarrier2 = new CyclicBarrier(num, new Runnable()
{
@Override
public void run()
{
System.out.println("启动行星发送机");
}
});
for(int i = 0; i < num; i++){
new Thread(new Runnable()
{
@Override
public void run()
{
try{
int t = new Random().nextInt(3000);
Thread.sleep(t);
System.out.println("运送火石" +cyclicBarrier2.getNumberWaiting());
if(cyclicBarrier2.getNumberWaiting() == 3){
cyclicBarrier2.reset();
System.out.println("reset后,等待线程数:" + cyclicBarrier2.getNumberWaiting());
}
cyclicBarrier2.await();
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
}
}
}
运行结果:
这是主线程
驾驶员0就位
驾驶员1就位
驾驶员2就位
驾驶员3就位
驾驶员4就位
驾驶员5就位
驾驶员6就位
驾驶员7就位
驾驶员8就位
驾驶员9就位
驾驶员集齐,开始运送火石
运送火石0
运送火石1
运送火石2
运送火石3
reset后,等待线程数:0
java.util.concurrent.BrokenBarrierException
at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)
at com.study.CyclicBarrierDemo$4.run(CyclicBarrierDemo.java:77)
at java.lang.Thread.run(Thread.java:748)
java.util.concurrent.BrokenBarrierException
at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)
at com.study.CyclicBarrierDemo$4.run(CyclicBarrierDemo.java:77)
at java.lang.Thread.run(Thread.java:748)
java.util.concurrent.BrokenBarrierException
at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)
at com.study.CyclicBarrierDemo$4.run(CyclicBarrierDemo.java:77)
at java.lang.Thread.run(Thread.java:748)
运送火石1
参考博文:
https://blog.csdn.net/xlgen157387/article/details/78218736