CountDownLatch和CyclicBarrier控制线程间的步调一致
CountDownLatch ‘线程间可见的计数器’
CountDownLatch latch = new CountDownLatch(num);// num=需要控制的线程数
latch.countDown();// 计数器减一 num--;
latch.await();// 等待计数器为0,num==0,然后继续执行下面的代码
复制代码
不支持循环使用CountDownLatch,每次使用必须重新初始化计数器;
CyclicBarrier ‘线程间可见、自动重置的计数器’
CyclicBarrier barrier = new CyclicBarrier(num, barrierAction);
// num=需要控制的线程数; barrierAction=计数器为0后执行的任务
barrier.await();
// 执行计数器-1,减完后如果计数器为0,则当前线程去执行barrierAction,否则阻塞线程;
复制代码
执行完barrierAction后计数器会自动重置不用重新初始化
借助CountDownLatch和CyclicBarrier优化串行程序
Executor executor = Executors.newFixedThreadPool(2);
// 计数器初始化为 2
CountDownLatch latch = new CountDownLatch(2);
// 查询数据A
executor.execute(()-> {
data_a =selectDb(a);
latch.countDown();
});
// 查询数据B
executor.execute(()-> {
data_b =selectEs(b);
latch.countDown();
});
// 等待两个查询操作结束
latch.await();
// 执行后续操作
res = mixData(data_a, data_b);
save(res)
复制代码
线程的执行图
查询数据和后续操作任然是串行的,实际上也可做到并行,在执行后续操作的时候进行下次数据的组装;反映在坐标图中则为:
//订单队列
Vector<Data> data_a;
// 派送单队列
Vector<Data> data_b;
// 执行回调的线程池
Executor executor = Executors.newFixedThreadPool(1);
final CyclicBarrier barrier = new CyclicBarrier(2, ()->{
executor.execute(()->check());
});
void check(){
Data a = data_a.remove(0);
Data b = data_b.remove(0);
res = check(a, b);
save(res);
}
void checkAll(){
Thread T1 = new Thread(()->{
while(存在数据a){
pos.add(selectDb());
// 等待
barrier.await();
}
});
T1.start();
Thread T2 = new Thread(()->{
while(存在数据b){
dos.add(selectEs());
// 等待
barrier.await();
}
});
T2.start();
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END