背景
Java多线程技术面试问得很多很多,而且在做脚本优化、接口异步调用、许多大型框架中使用非常广泛,提升性能巨大。不过实际工作中的业务开发,更多是为了保证业务的安全可靠和节省性能开销,都没怎么使用到。最近做了一个异步调用接口的需求,好久没用过了,一时还有点想不起来,还得看看java api文档,记录一下方便以后查看。
前置知识
异步的原理
Java 异步的基本原理是利用多线程和回调函数。在异步操作中,主线程不必等待异步任务完成,而是可以继续执行其他任务。当异步任务完成时,通过回调函数或者其他机制通知主线程。
-
启动异步任务: 使用线程、CompletableFuture 或者其他异步编程工具启动异步任务,使其在新线程中执行。
-
主线程不阻塞: 主线程可以继续执行其他任务,而不必等待异步任务完成。
-
异步任务完成时通知主线程: 当异步任务完成时,通过回调函数、CompletableFuture 的 thenApply、thenAccept 等方法,或者其他方式通知主线程,以执行相应的逻辑。
处理异步任务的结果: 主线程在接收到异步任务完成的通知后,可以处理异步任务的结果。
异步的方式
- 多线程
在 Java 中,多线程是实现异步操作的基础。通过创建线程,可以在应用程序中并发执行多个任务,实现异步操作的效果。Java 提供了 Thread 类和 Runnable 接口,使得创建和管理线程变得相对容易。
// 示例:创建并启动一个线程
Thread myThread = new Thread(() -> {
// 异步任务逻辑
System.out.println("异步任务在新线程中执行");
});
myThread.start(); // 启动线程
- Future 和 CompletableFuture
Future 接口是 Java 中处理异步操作的一种方式,用于表示一个异步计算的结果。但它的使用相对受限,因为它只提供了对异步操作结果的简单访问。
// 示例:使用 Future
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> futureResult = executorService.submit(() -> {
// 异步任务逻辑
return "异步任务的结果";
});
// 阻塞等待异步操作完成
String result = futureResult.get();
System.out.println("异步任务的结果:" + result);
CompletableFuture 是 Future 的一个扩展,提供更丰富的异步编程功能。它支持回调、组合多个异步操作等特性。
// 示例:使用 CompletableFuture
CompletableFuture<String> futureResult = CompletableFuture.supplyAsync(() -> {
// 异步任务逻辑
return "异步任务的结果";
});
// 注册回调函数
futureResult.thenAccept(result -> System.out.println("异步任务的结果:" + result));
- 回调函数
回调函数是异步编程中常见的一种机制。通过回调函数,你可以指定在异步操作完成时执行的逻辑。在 CompletableFuture 中,thenApply、thenAccept、thenRun 等方法就是用于注册回调函数的。
CompletableFuture<String> futureResult = CompletableFuture.supplyAsync(() -> {
// 异步任务逻辑
return "异步任务的结果";
});
// 注册回调函数
futureResult.thenAccept(result -> System.out.println("异步任务的结果:" + result));
实战操作
需求:需要分别调用A接口和B接口,两个返回结果之间没有关联。
方式一:多线程
public class AsyncExampleThread {
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
String resultA = requestInterfaceA();
System.out.println("接口A的返回结果:" + resultA);
});
Thread threadB = new Thread(() -> {
String resultB = requestInterfaceB();
System.out.println("接口B的返回结果:" + resultB);
});
// 启动线程
threadA.start();
threadB.start();
// 主线程等待子线程执行完成
try {
threadA.join();
threadB.join();
} catch (InterruptedException e) {