CompletableFuture
在现代编程中,异步操作是提升程序性能和响应性的关键技术。Java 8 引入的CompletableFuture
类,极大地简化了异步编程的复杂性,提供了一种强大且灵活的方式来处理异步任务及其结果。本文将深入探讨CompletableFuture
的特性、使用方法以及在实际应用中的优势,并通过丰富的代码示例帮助读者全面掌握这一重要工具。
CompletableFuture 概述
CompletableFuture
实现了Future
和CompletionStage
接口,它不仅能够获取异步任务的结果,还能在任务完成时进行各种操作,比如执行回调函数、组合多个异步任务等。与传统的Future
相比,CompletableFuture
具有以下显著特点:
- 异步操作的链式调用:可以通过链式调用的方式,对异步任务进行一系列的操作,无需手动管理线程和等待任务完成。
- 自动回调机制:当异步任务完成时,会自动触发注册的回调函数,无需额外的轮询或等待操作。
- 支持多个异步任务的组合:能够方便地组合多个异步任务,如并行执行、按顺序执行、等待所有任务完成或等待任一任务完成等。
CompletableFuture 基本用法
1. 创建 CompletableFuture
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
// 创建一个异步任务,返回一个CompletableFuture对象
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 模拟异步任务的执行,这里使用Thread.sleep模拟耗时操作
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "任务完成,返回结果";
});
// 获取异步任务的结果,这是一个阻塞操作
try {
String result = future.get();
System.out.println("异步任务结果: " + result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
在上述代码中,通过CompletableFuture.supplyAsync
方法创建了一个异步任务,该方法接受一个Supplier
接口的实现,返回一个CompletableFuture
对象。在supplyAsync
方法中,定义了异步任务的具体逻辑,这里通过Thread.sleep
模拟了一个耗时 2 秒的操作,最后返回任务结果。通过future.get()
方法获取异步任务的结果,该方法会阻塞当前线程,直到任务完成并返回结果。
2. 异步任务完成后的回调
import java.util.concurrent.CompletableFuture;
public class CompletableFutureCallbackExample {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "任务完成";
}).thenAccept(result -> {
System.out.println("接收到任务结果: " + result);
});
// 主线程不能立即退出,否则异步任务可能无法执行
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在这段代码中,thenAccept
方法用于注册一个回调函数,当异步任务完成并返回结果时,会自动调用该回调函数。thenAccept
方法接受一个Consumer
接口的实现,它会将异步任务的结果作为参数传递给回调函数。在示例中,回调函数只是简单地打印接收到的任务结果。
3. 处理异步任务的异常
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExceptionExample {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
if (Math.random() > 0.5) {
throw new RuntimeException("任务执行出错");
}
return "任务完成";
}).exceptionally(ex -> {
System.out.println("捕获到异常: " + ex.getMessage());
return "默认结果";
}).thenAccept(result -> {
System.out.println("最终结果: " + result);
});
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
exceptionally
方法用于处理异步任务执行过程中抛出的异常。它接受一个Function
接口的实现,当异步任务抛出异常时,会调用该函数,将异常作为参数传递进去,函数返回一个默认值,作为最终的结果。在示例中,通过Math.random()
模拟了任务可能抛出异常的情况,当异常发生时,exceptionally
方法捕获异常并返回一个默认结果,然后thenAccept
方法处理最终结果。
CompletableFuture 组合异步任务
1. 多个异步任务并行执行并等待所有任务完成
import java.util.concurrent.CompletableFuture;
public class CompletableFutureAllOfExample {
public static void main(String[] args) {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "任务1完成";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "任务2完成";
});
CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(future1, future2);
allOfFuture.join();
try {
System.out.println("任务1结果: " + future1.get());
System.out.println("任务2结果: " + future2.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
CompletableFuture.allOf
方法用于将多个CompletableFuture
组合在一起,等待所有任务完成。allOf
方法返回一个新的CompletableFuture<Void>
,当所有传入的CompletableFuture
都完成时,这个新的CompletableFuture
也会完成。在示例中,创建了两个异步任务future1
和future2
,然后使用allOf
方法将它们组合起来,通过join
方法等待所有任务完成,最后获取并打印每个任务的结果。
2. 多个异步任务并行执行并等待任一任务完成
import java.util.concurrent.CompletableFuture;
public class CompletableFutureAnyOfExample {
public static void main(String[] args) {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "任务1完成";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "任务2完成";
});
CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(future1, future2);
try {
System.out.println("最先完成的任务结果: " + anyOfFuture.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
CompletableFuture.anyOf
方法用于将多个CompletableFuture
组合在一起,只要其中任一任务完成,这个新的CompletableFuture
就会完成,并返回最先完成的任务的结果。在示例中,创建了两个异步任务future1
和future2
,使用anyOf
方法将它们组合,通过get
方法获取最先完成的任务结果并打印。
结语
感谢您的阅读!如果您对 CompletableFuture
或其他并发编程话题有任何疑问或见解,欢迎继续探讨。