前面介绍了CountDownLatch,可以实现计数。达到指定的数后,就会同时执行。
那么CyclicBarrier跟CountDownLatch实现的功能差不多。
import java.util.Random;
import java.util.concurrent.*;
/**
* await()就好比是屏障,经过指定数量的屏障才可以执行最后的线程。
* 或者说是一直等待,直到await()的数量是指定的数量后才会执行下面的
*/
public class CyclicbarrierTest {
private static final int THREAD_NUM = 3;
public static void main(String[] args) {
CyclicbarrierTest t = new CyclicbarrierTest();
t.tttt();
}
public void tttt(){
CyclicBarrier cb = new CyclicBarrier(THREAD_NUM, new Runnable() {
public void run() {
System.out.println("都准备好了");
try {
Thread.sleep(2000);
return;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
ThreadPoolExecutor executor = new ThreadPoolExecutor(THREAD_NUM,THREAD_NUM,0, TimeUnit.SECONDS,new LinkedBlockingQueue());
for (int i = 1; i <= THREAD_NUM; i++) {
Task t = new Task(""+i,cb);
executor.execute(t);
}
System.out.println("我的任务已经分派完毕...");
}
class Task implements Runnable{
private CyclicBarrier cb;
private String taskName;
public Task(){
}
public Task(String taskName,CyclicBarrier cb){
this.taskName = taskName;
this.cb = cb;
}
public void run() {
try {
Random r = new Random();
int slt = r.nextInt(10);
Thread.sleep(slt*1000);
System.out.println(taskName+"使用了"+slt+"秒,准备好了");
cb.await();
System.out.println(taskName+"继续执行");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
执行结果:
我的任务已经分派完毕...
1使用了3秒,准备好了
3使用了4秒,准备好了
2使用了9秒,准备好了
都准备好了
2继续执行
1继续执行
3继续执行
await()方法在等待所有的线程都通过了屏障,就会执行CyclicBarrier内部的线程,执行完内部线程后,子线程会继续执行。
同时我们看到看到CyclicBarrier会阻塞子线程,不会阻塞主线程。
可以看到是分两步的:
第一步:所有的线程都会阻塞,然后执行CyclicBarrier内部线程;
第二部:CyclicBarrier内部线程执行完后,各子线程又开始继续运行。
同时在CyclicBarrier内部线程中还可以继续调用CyclicBarrier。
public static void main(String[] args) {
CyclicbarrierTest t = new CyclicbarrierTest();
t.tttt();
}
public void tttt(){
CyclicBarrier cb = new CyclicBarrier(THREAD_NUM, new Runnable() {
public void run() {
System.out.println("都准备好了");
try {
Thread.sleep(2000);
System.out.println("调用下一层");
//在CyclicBarrier调用下一层CyclicBarrier
tt();
return;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
ThreadPoolExecutor executor = new ThreadPoolExecutor(THREAD_NUM,THREAD_NUM,0, TimeUnit.SECONDS,new LinkedBlockingQueue());
for (int i = 1; i <= THREAD_NUM; i++) {
Task t = new Task(""+i,cb);
executor.execute(t);
}
System.out.println("我的任务已经分派完毕...");
}
public void tt(){
CyclicBarrier cb = new CyclicBarrier(THREAD_NUM, new Runnable() {
public void run() {
System.out.println("我是另一个CyclicBarrier");
try {
Thread.sleep(2000);
return;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
ThreadPoolExecutor executor = new ThreadPoolExecutor(THREAD_NUM,THREAD_NUM,0, TimeUnit.SECONDS,new LinkedBlockingQueue());
for (int i = 1; i <= THREAD_NUM; i++) {
Task t = new Task("=>"+i,cb);
executor.execute(t);
}
}
执行结果:
我的任务已经分派完毕...
1使用了5秒,准备好了
3使用了9秒,准备好了
2使用了9秒,准备好了
都准备好了
调用下一层
2继续执行
1继续执行
3继续执行
=>3使用了7秒,准备好了
=>1使用了7秒,准备好了
=>2使用了8秒,准备好了
我是另一个CyclicBarrier
=>2继续执行
=>3继续执行
=>1继续执行