一 点睛
CyclicBarrier 的作用就是会让所有线程都等待完成后才会继续下一步行动。
二 实战1——基础用法
1 代码
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
// 它的作用就是会让所有线程都等待完成后才会继续下一步行动。
// 场景:一个线程组的线程需要等待所有线程完成任务后再继续执行下一次任务
public class T07_TestCyclicBarrier {
public static void main(String[] args) {
// 第一种方式
// CyclicBarrier barrier = new CyclicBarrier(20);
// 第二种方式
// 循环栅栏,满了20,调用第2个参数指定的代码
CyclicBarrier barrier = new CyclicBarrier(20, () -> System.out.println("满人,发车"));
// 第三种方式
/*CyclicBarrier barrier = new CyclicBarrier(20, new Runnable() {
@Override
public void run() {
System.out.println("满人,发车");
}
});*/
for (int i = 0; i < 100; i++) {
new Thread(() -> {
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
2 测试
满人,发车
满人,发车
满人,发车
满人,发车
满人,发车
三 实战2——更形象的例子
1 代码
import java.util.concurrent.CyclicBarrier;
// 场景:有3个任务,一个是读数据库,一个是读文件,一个是读网络,先串行操作,再将读到的所有数据进行拼接,这样做效率比较低。
// 如果采用 CyclicBarrier ,让3个任务变成3个线程,让他们并行完成各自的任务,当等到这3个任务都完成后,冲破栅栏,再组织数据,效率将大幅提高。
public class CyclicBarrierDemo {
static class TaskThread extends Thread {
CyclicBarrier barrier;
public TaskThread(CyclicBarrier barrier) {
this.barrier = barrier;
}
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println(getName() + " 到达栅栏 A");
barrier.await();
System.out.println(getName() + " 冲破栅栏 A");
Thread.sleep(2000);
System.out.println(getName() + " 到达栅栏 B");
barrier.await();
System.out.println(getName() + " 冲破栅栏 B");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int threadNum = 5;
CyclicBarrier barrier = new CyclicBarrier(threadNum, new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 完成最后任务");
}
});
for(int i = 0; i < threadNum; i++) {
new TaskThread(barrier).start();
}
}
}
2 测试
Thread-0 到达栅栏 A
Thread-3 到达栅栏 A
Thread-1 到达栅栏 A
Thread-4 到达栅栏 A
Thread-2 到达栅栏 A
Thread-2 完成最后任务
Thread-2 冲破栅栏 A
Thread-4 冲破栅栏 A
Thread-1 冲破栅栏 A
Thread-0 冲破栅栏 A
Thread-3 冲破栅栏 A
Thread-3 到达栅栏 B
Thread-1 到达栅栏 B
Thread-0 到达栅栏 B
Thread-2 到达栅栏 B
Thread-4 到达栅栏 B
Thread-4 完成最后任务
Thread-4 冲破栅栏 B
Thread-1 冲破栅栏 B
Thread-3 冲破栅栏 B
Thread-2 冲破栅栏 B
Thread-0 冲破栅栏 B
3 分析
A 任务完成后,才能进行 B任务。
从打印结果可以看出,所有线程会等待全部线程到达栅栏之后才会继续执行,并且最后到达的线程会完成 Runnable 的任务。