比如一个场景,需要先调用几个接口,获取到调用结果之后统一处理

对于这种情况,第一的思路就是异步多线程获取接口返回结果

那么就是对于接口的调用,采用了多线程的处理方式

那么更好的解决方法就是使用了CountDownLatch

在CountDownLatch中,初始化传入一个计数器,在计数器中,进行调用多个接口,调用一次将Count减一,让主线程进行等待,等待降为0在进行唤醒执行处理

接下来的代码就是关于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来实现同步问题,CylicBarrier也需要传入一个初始化数值,和一个回调函数

计数器为0的时候,会调用这个回调函数

而且CylicBarrier支持在归为0后重新再重置为初始化数值

对于上面的代码来说,就是多个查询接口多个线程,每个任务一旦完成就进行减一

// 订单队列

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和CylicBarrier是Java并发包两个工具类,看起来功能相似

但是CountDownLatch更像是一次使用的,一个线程等待多个线程

CylicBarrier是一组线程之间相互等待,而且可以循环利用的

发表评论

邮箱地址不会被公开。 必填项已用*标注