线程的奥秘:如果你碰到一个题目需要执行完10个或者n个才能轮到下一个线程执行的案例你需要采用怎样的方法?这时候简单实用倒计时器CountDownLatch
现在做一个火箭发射前检查完10道工序再发射的多线程控制原型:
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLactateDemo implements Runnable {
static CountDownLactateDemo demo=new CountDownLactateDemo();
static int i=0;
static final CountDownLatch countDownLatch=new CountDownLatch(10);//计数数量为10,10个线程执行完才轮到下一个来执行。
@Override
public void run() {
try {
Thread.sleep(new Random().nextInt(10)*1000);
i++;
System.out.println( i+" "+"check process");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
ExecutorService exec= Executors.newFixedThreadPool(10);
for (int j=0;j<10;j++){
exec.submit(demo);
}
countDownLatch.await();//要求主线程等待10个线程执行完毕
System.out.println( "launch");//执行完10个后火箭才发射
exec.shutdown();
}
}
结果:
这时候我们要求主线程只等待9个检查工序就发射火箭,发送火箭后执行第10个线程,通知发射成功类似。只需要修改等待线程为9个就可以了,输出结果为:
循环栅栏可以视作为反复使用的倒数计数器
假设一个长官命令10个士兵集合,集合完毕长官发布集合完毕,然后10个士兵完成任务后长官发布任务完成完毕。都必须等这线程任务完成才可以发布,代码如下:
import java.util.Random;
import java.util.concurrent.*;
public class CyclicBarrierDemo {
public static class Sodier implements Runnable{
private CyclicBarrier cyclic;
private String soldier;
Sodier(CyclicBarrier cyclicBarrier,String soldierName){
this.cyclic=cyclicBarrier;
this.soldier=soldierName;
}
@Override
public void run() {
//等待所有士兵到达
try {
cyclic.await();
//全部达到后执行下一步
doWork();
cyclic.await();
//等待所有线程doWork任务完成
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
void doWork(){
System.out.println( soldier+" "+"任务完成!");
}
}
public static class BarrierRun implements Runnable{
boolean flag;
int N=10;
BarrierRun(boolean flag,int N){
this.flag=flag;
this.N=N;
}
@Override
public void run() {
if (flag){
System.out.println("长官:"+N+ "个士兵集合完毕");
flag=false;
}else{
System.out.println( "长官"+N+"个士兵任务完成");
}
}
}
public static void main(String[] args) throws InterruptedException {
boolean flag=true;
final int N=10;
Thread[] thread=new Thread[N];
CyclicBarrier cyclicBarrier=new CyclicBarrier(N,new BarrierRun(true,N));
//加入10个等待线程,完成计数器指标后执行第二参数new BarrierRun(true,N),只要调用await后计数完毕都会调用该线程
System.out.println( "开始集合队伍");
for (int i=0;i<N;++i){
System.out.println( "士兵"+i+"报道!");
thread[i]=new Thread(new Sodier(cyclicBarrier,"士兵"+i));
thread[i].start();;
}
}
}
打印结果如下:
开始集合队伍
士兵0报道!
士兵1报道!
士兵2报道!
士兵3报道!
士兵4报道!
士兵5报道!
士兵6报道!
士兵7报道!
士兵8报道!
士兵9报道!
长官:10个士兵集合完毕
士兵8 任务完成!
士兵1 任务完成!
士兵3 任务完成!
士兵5 任务完成!
士兵7 任务完成!
士兵9 任务完成!
士兵2 任务完成!
士兵0 任务完成!
士兵4 任务完成!
士兵6 任务完成!
长官10个士兵任务完成
Process finished with exit code 0