概要
多线程+CountDownLatch
线程池+CompletableFuture
CompletableFuture介绍
在Java中,有些任务单线程执行时间长,一般会使用多线程增加并发提高运行速率。但很多情况下,需要所有子线程执行完,才能往下执行主线程,一般我们会使用这些方案:
1、多线程+CountDownLatch
2、线程池+CompletableFuture
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(10);
for (int i=0; i<4; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 运行");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown();
}
}
}).start();
}
System.out.println("等待子线程运行结束");
latch.await(10, TimeUnit.SECONDS);
System.out.println("子线程运行结束");
}
缺点:经常会忘记写latch.countDown();,或者latch.countDown()未执行,导致线程阻塞
1、多个子线程全部执行完,才能继续往下,阻塞主线程
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(8, 10, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(Integer.MAX_VALUE));
CompletableFuturetask3 = CompletableFuture.runAsync(() -> { //TODO do something }, threadPoolExecutor); CompletableFuture task5 = CompletableFuture.runAsync(() -> { //TODO do something }, threadPoolExecutor); CompletableFuture headerFuture = CompletableFuture.allOf(task3, task5); headerFuture.join();
//继续主线程
2、多个子线程,每个单独异步执行,不阻塞主线程
CompletableFuture
CompletableFuture
3、exceptionally使用,处理异常
CompletableFuture.runAsync(() -> { //TODO do something }, threadPoolExecutor).exceptionally(e -> { if (e instanceof CompletionException || e instanceof ExecutionException) { if (e.getCause() != null) { e = e.getCause(); } } return MxtyDdlCompletableDTO.builder().throwable(e).build(); });
4、多个子线程执行完成,统计处理结果
List> futureList = new ArrayList<>(); for (List list : partition) { CompletableFuture future = CompletableFuture.supplyAsync(() -> { tableCountNumSql(dqlDecorator, list, map); return MxtyDdlCompletableDTO.builder().build(); }, ddlTaskPool).exceptionally(e -> { if (e instanceof CompletionException || e instanceof ExecutionException) { if (e.getCause() != null) { e = e.getCause(); } } return MxtyDdlCompletableDTO.builder().throwable(e).build(); }); futureList.add(future); }
for (CompletableFuturefuture : futureList) { MxtyDdlCompletableDTO dto = future.join(); if (dto == null || dto.getThrowable() != null) { } }
CompletableFuture是Java中的一个类,表示异步计算的未来结果。它是java.util.concurrent包的一部分,作为Future接口的增强功能在Java 8中引入的。
CompletableFuture类的一些关键特性包括:
1. 异步执行:CompletableFuture允许您异步执行任务,这意味着调用线程可以在不等待任务完成的情况下继续执行。
2. 完成阶段:CompletableFuture引入了CompletionStage的概念,它表示可能最终完成并返回值或异常的计算阶段。CompletionStage提供了将多个阶段链接在一起并定义它们之间依赖关系的方法。
3. 回调和可组合性:CompletableFuture支持回调,在未来完成时执行。您可以使用 `thenApply()` 、 `thenAccept()` 和 `thenRun()` 等方法附加回调。此外,CompletableFuture还提供了 `thenCompose()` 和 `thenCombine()` 等方法,用于组合多个未来。
4. 异常处理:CompletableFuture允许您处理计算过程中发生的异常,使用 `exceptionally()` 和 `handle()` 等方法。这些方法提供了处理和恢复异常的灵活性。
5. 异步组合器:CompletableFuture提供了一组称为"组合器"的方法,允许您组合多个未来、等待它们全部完成或选择第一个完成的未来。
总的来说,CompletableFuture为Java中的异步计算提供了强大而灵活的方式,使您能够编写更高效和响应性的代码。