Java - 等待线程 CountDownLatch

1. 完整使用案例

private static final int CPUS = Runtime.getRuntime().availableProcessors();
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(CPUS * 3, CPUS * 3, 1L, HOURS, new LinkedBlockingDeque<>(6000), new ThreadFactoryBuilder().setNameFormat("test-executor-pool-%d").build());

// 有两组数据, 在多线程的前提下, 必须先执行完第一组, 才能执行第二组
List<User> list1 = new ArrayList<>();
List<User> list2 = new ArrayList<>();

if (CollectionUtils.isNotEmpty(list1)) {
    CountDownLatch list1Latch = new CountDownLatch(list1.size());
    for (User user : list1) {
        executor.execute(() -> {
            try {
                // do something
            } catch (Exception ex) {
                log.error(">>> 线程list1Latch编号: {}, 线程异常:{}", list1Latch.getCount(), getStackTrace(ex));
            } finally {
                list1Latch.countDown();
            }
        });
    }
    try {
        list1Latch.await(3, TimeUnit.MINUTES);
    } catch (InterruptedException ex) {
        log.error("线程处理超过3分钟, 定义为执行失败");
        throw new Exception("处理失败");
    }
}

if (CollectionUtils.isNotEmpty(list2)) {
    CountDownLatch list2Latch = new CountDownLatch(list2.size());
	// ... ...
}

2. 自己摸索的等待线程实现

private static final int CPUS = Runtime.getRuntime().availableProcessors();
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(CPUS * 3, CPUS * 3, 1L, HOURS, new LinkedBlockingDeque<>(6000), new ThreadFactoryBuilder().setNameFormat("test-executor-pool-%d").build());

@Test
public void 等待线程测试() throws Exception {
    List<String> result = new ArrayList<>();
    List<String> strList = new ArrayList<>();
    strList.add("100"); strList.add("200"); strList.add("300"); strList.add("400"); strList.add("500");
    strList.add("600"); strList.add("700"); strList.add("800"); strList.add("900"); strList.add("1000"); strList.add("1100");
    System.out.println("strList.size = " + strList.size() + "; strList = " + strList);
    CountDownLatch countDownLatch = new CountDownLatch(strList.size());
    System.out.println("count = " + countDownLatch.getCount());
    List<String> collect1 = strList.stream().filter(s -> Integer.parseInt(s) <= 500).collect(toList());
    System.out.println("collect1.size = " + collect1.size() + "; collect1 = " + collect1);
    List<String> collect2 = strList.stream().filter(s -> Integer.parseInt(s) > 500).collect(toList());
    System.out.println("collect2.size = " + collect2.size() + "; collect2 = " + collect2);
    for (String s : collect1) {
        executor.execute(() -> {
            try {
                System.out.println("[1] 线程内 s = " + s);
                result.add(s);
            } catch (Exception ex) {
                System.out.println("模版文件数据解析对应的countDownLatch编号 = " + countDownLatch.getCount());
            } finally {
                countDownLatch.countDown();
                System.out.println("[1] latch1 = " + countDownLatch);
            }
        });
    }
    // 集合1结束计数
    long l1 = strList.size() - collect1.size();
    waitAndCheck(l1, countDownLatch);
    System.out.println("第一个线程结束的 result = " + result);
    System.out.println("------------------------------");
    for (String s : collect2) {
        executor.execute(() -> {
            try {
                System.out.println("[2] 线程内 s = " + s);
                result.add(s);
            } catch (Exception ex) {
                System.out.println("模版文件数据解析对应的countDownLatch编号 = " + countDownLatch.getCount());
            } finally {
                countDownLatch.countDown();
                System.out.println("[2] countDownLatch = " + countDownLatch);
            }
        });
    }
    // 集合2结束计数
    waitAndCheck(0L, countDownLatch);
    System.out.println("第二个线程结束的 result = " + result);
}

/**
 * 手动等待线程
 */
private void waitAndCheck(long checkNum, CountDownLatch latch) throws Exception {
    boolean overtime = false;
    long startTime = System.currentTimeMillis();
    while (true) {
        if (latch.getCount() == checkNum) {
            break;
        }
        long endTime = System.currentTimeMillis();
        if (endTime - startTime >= 30000) {// 30秒超时
            overtime = true;
            break;
        }
    }
    if (overtime) {
        throw new Exception("EXCEL处理超时, 请减少数据量后重试或联系管理员!");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值