–我们在使用多线程时,经常会new一个内部类或者使用ThreadService,等自定义线程池提供的线程执行方法,但这些均都是异步方法,即主方法一经调用就会立刻返回结束,留下子线程在后台默默运行,在接口返回中无法知道子线程到底执行到哪一步,接下来就给大家讲解一下如何使用同步多线程(CountDownLatch计数器与Callable可回收),让主线程一直等待所有子线程执行完成后再返回,对一些特殊场景非常有帮助,接下来列举具体方法
版本一(CountDownLatch 计数器):
public void synManyThread() {
List<String> list = Arrays.asList("1", "2", "3");
// 计数器
CountDownLatch downLatch = new CountDownLatch(list.size());
// 创建线程
ExecutorService executorService = null;
try {
executorService = Executors.newCachedThreadPool();
for (String item : list) {
// 开启线程
executorService.execute(() -> {
try {
// 业务处理
System.out.println(item);
} finally {
downLatch.countDown();
}
});
}
downLatch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
if (executorService != null) {
executorService.shutdown();
}
}
}
此方法中CountDownLatch会创建一个初始大小的计数器,每执行完一个子线程数量就会叠加,直到最后计数器满足数量时主线程才会执行到downLatch.await()下一步,但此方法虽简单,也有不足之处,无法接收所有子线程的结果
版本二(Callable可回收):
public void synManyThread() {
// 创建线程池
ExecutorService executorService = Executors.newCachedThreadPool();
List<String> list = Arrays.asList("1", "2", "3");
try {
// 创建带有返回值集合
List<Future<String>> futures = new ArrayList<>();
list.forEach(item -> {
// 子线程
Callable<String> callable = processing(item);
futures.add(executorService.submit(callable));
});
try {
// 获取所有并发任务的运行结果
for (Future<String> f : futures) {
// 从Future对象上获取任务的返回值,并输出到控制台
log.debug("子线程执行完成,订单号:{}", f.get());
}
} catch (Exception e) {
log.error("子线程执行异常,原因:{}", e.toString());
}
} catch (Exception e) {
log.error("异常:{}", e.toString());
} finally {
if (!executorService.isShutdown()) {
executorService.shutdown();
}
}
}
/**
* 业务处理
*/
private Callable<String> processing(String item) {
Callable<String> callable = () -> {
// 业务处理
return "成功:" + item;
};
return callable;
}
此方法将所有子线程的返回结果都接收到futures中,主线程在for循环中接收到所有子线程的返回值后再执行下一步
本次教程到这里就结束了,希望大家多多关注支持(首席摸鱼师 微信同号),持续跟踪最新文章吧~