CountDownLatch 和 CyclicBarrier 保证线程同步

CountDownLatch

// 创建 2 个线程的线程池

Executor executor =

Executors.newFixedThreadPool(2);

while(存在未对账订单){

// 计数器初始化为 2

CountDownLatch latch =

new CountDownLatch(2);

// 查询未对账订单

executor.execute(()-> {

pos = getPOrders();

latch.countDown();

});

// 查询派送单

executor.execute(()-> {

dos = getDOrders();

latch.countDown();

});

 

// 等待两个查询操作结束

latch.await();

 

// 执行对账操作

diff = check(pos, dos);

// 差异写入差异库

save(diff);

}

 

CyclicBarrier

// 订单队列

Vector<P> pos;

// 派送单队列

Vector<D> dos;

// 执行回调的线程池

Executor executor =

Executors.newFixedThreadPool(1);

final CyclicBarrier barrier =

new CyclicBarrier(2, ()->{

executor.execute(()->check());

});

 

void check(){

P p = pos.remove(0);

D d = dos.remove(0);

// 执行对账操作

diff = check(p, d);

// 差异写入差异库

save(diff);

}

 

void checkAll(){

// 循环查询订单库

Thread T1 = new Thread(()->{

while(存在未对账订单){

// 查询订单库

pos.add(getPOrders());

// 等待

barrier.await();

}

});

T1.start();

// 循环查询运单库

Thread T2 = new Thread(()->{

while(存在未对账订单){

// 查询运单库

dos.add(getDOrders());

// 等待

barrier.await();

}

});

T2.start();

}

CountDownLatch 和 CyclicBarrier 是 Java 并发包提供的两个非常易用的线程同步工具类,这两个工具类用法的区别在这里还是有必要再强调一下:CountDownLatch 主要用来解决一个线程等待多个线程的场景,可以类比旅游团团长要等待所有的游客到齐才能去下一个景点;而CyclicBarrier 是一组线程之间互相等待,更像是几个驴友之间不离不弃。除此之外 CountDownLatch 的计数器是不能循环利用的,也就是说一旦计数器减到 0,再有线程调用 await(),该线程会直接通过。但CyclicBarrier 的计数器是可以循环利用的,而且具备自动重置的功能,一旦计数器减到 0 会自动重置到你设置的初始值。除此之外,CyclicBarrier 还可以设置回调函数,可以说是功能丰富。

本章的示例代码中有两处用到了线程池,你现在只需要大概了解即可,因为线程池相关的知识咱们专栏后面还会有详细介绍。另外,线程池提供了 Future 特性,我们也可以利用 Future 特性来实现线程之间的等待,这个后面我们也会详细介绍。

此条目发表在java分类目录,贴了, , , 标签。将固定链接加入收藏夹。