@Slf4j
public class BatchRefundDemo
{
// 定义线程池
public static final ExecutorService EXECUTOR_SERVICE = new ThreadPoolExecutor(10, 10, 0 L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue < > (20));
@Test
public void batchRefund() throws InterruptedException
{
// state 初始化为 30
CountDownLatch countDownLatch = new CountDownLatch(30);
RefundDemo refundDemo = new RefundDemo();
// 准备 30 个商品
List items = Lists.newArrayListWithCapacity(30);
for(int i = 0; i < 30; i++)
{
items.add(Long.valueOf(i + ""));
}
// 准备开始批量退款
List futures = Lists.newArrayListWithCapacity(30);
for(Long item: items)
{
// 使用 Callable,因为我们需要等到返回值
Future future = EXECUTOR_SERVICE.submit(new Callable()
{
@Override
public Boolean call() throws Exception
{
boolean result = refundDemo.refundByItem(item);
// 每个子线程都会执行 countDown,使 state -1 ,但只有最后一个才能真的唤醒主线程
countDownLatch.countDown();
return result;
}
});
// 收集批量退款的结果
futures.add(future);
}
log.info("30 个商品已经在退款中");
// 使主线程阻塞,一直等待 30 个商品都退款完成,才能继续执行
countDownLatch.await();
log.info("30 个商品已经退款完成");
// 拿到所有结果进行分析
List result = futures.stream().map(fu - >
{
try
{
// get 的超时时间设置的是 1 毫秒,是为了说明此时所有的子线程都已经执行完成了
return (Boolean) fu.get(1, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
catch (ExecutionException e)
{
e.printStackTrace();
}
catch (TimeoutException e)
{
e.printStackTrace();
}
return false;
}).collect(Collectors.toList());
// 打印结果统计
long success = result.stream().filter(r - > r.equals(true)).count();
log.info("执行结果成功{},失败{}", success, result.size() - success);
}
}
CountDownLatch锁的应用
于 2023-09-06 10:07:49 首次发布