java异步编程

Java 提供了几种异步编程方式,尤其是在 Java 8 引入的 CompletableFuture 和 Java 11 的 HttpClient 中,能够实现异步操作。

1. CompletableFuture (Java 8)

CompletableFuture 是 Java 中用于处理异步任务的类,它提供了类似于 C# async/await 的功能,可以链式操作并组合多个异步任务。

示例:使用 CompletableFuture

import java.util.concurrent.CompletableFuture;

public class AsyncExample {
    public static void main(String[] args) {
        // 异步调用
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 模拟耗时操作
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello, World!";
        });

        // 异步完成后执行操作
        future.thenAccept(result -> {
            System.out.println("Result: " + result);
        });

        // 继续执行其他任务
        System.out.println("Doing other work...");

        // 主线程等待异步操作完成
        future.join();  // 等待异步任务完成
    }
}

在这个示例中,supplyAsync 方法用于启动一个异步任务,thenAccept 用于处理任务完成后的结果。类似于 C# 中的 awaitjoin() 会阻塞,直到异步任务完成。

2. HttpClient (Java 11)

Java 11 引入了新的 HttpClient,支持异步 HTTP 请求,结合 CompletableFuture 实现异步调用。

示例:使用 HttpClient 进行异步 HTTP 请求

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;

public class AsyncHttpClientExample {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(new URI("https://jsonplaceholder.typicode.com/posts/1"))
            .build();

        // 异步发送请求
        CompletableFuture<HttpResponse<String>> future = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());

        // 处理响应
        future.thenApply(HttpResponse::body)
              .thenAccept(System.out::println)
              .join();  // 等待异步任务完成
    }
}

这里的 sendAsync 方法是非阻塞的,返回一个 CompletableFuture,可以在响应准备好时处理。

3. 使用第三方库

如果你想要更接近 C# async/await 语法的体验,可以使用第三方库如 Project LoomReactiveX (RxJava),它们可以帮助简化异步编程,特别是在并发任务较多的场景下。

1. 基本概念

  • CompletableFutureFuture 的增强版,支持非阻塞的异步操作。它允许你通过链式调用处理异步任务的结果。
  • 支持异步计算、组合多个任务、处理异常等功能,非常适用于并发和异步编程。

2. 创建 CompletableFuture

  • 直接创建已完成的 CompletableFuture:
    CompletableFuture<String> completedFuture = CompletableFuture.completedFuture("Hello");
    
  • 异步任务:使用 runAsyncsupplyAsync 启动异步任务。
    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        // 任务逻辑
    });
    
    CompletableFuture<String> futureWithResult = CompletableFuture.supplyAsync(() -> {
        return "Result";
    });
    

3. 组合任务

  • thenApply:对任务结果进行转换或处理。
    future.thenApply(result -> result.toUpperCase());
    
  • thenAccept:处理结果但不返回值。
    future.thenAccept(result -> System.out.println(result));
    
  • thenRun:在任务完成后执行某个操作,不关心结果。
    future.thenRun(() -> System.out.println("Task completed"));
    
  • thenCombine:将两个异步任务的结果进行组合。
    CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + result2);
    

4. 异常处理

  • exceptionally:处理异常并返回替代结果。
    future.exceptionally(ex -> {
        System.out.println("Error: " + ex.getMessage());
        return "Fallback result";
    });
    
  • handle:无论任务成功或失败,都会执行,可以分别处理结果和异常。
    future.handle((result, ex) -> {
        if (ex != null) {
            System.out.println("Error: " + ex.getMessage());
            return "Fallback result";
        } else {
            return result;
        }
    });
    

5. 组合多个 CompletableFuture

  • allOf:等待所有 CompletableFuture 完成。
    CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);
    
  • anyOf:只要有一个 CompletableFuture 完成就继续。
    CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2);
    

6. 异步回调执行器

  • 可以使用自定义线程池来执行异步任务,而不是使用默认的 ForkJoinPool
    CompletableFuture.supplyAsync(() -> "Result", executor);
    

7. 典型用例

  • 并行任务执行:当需要同时执行多个异步任务时,可以通过 thenCombineallOf 进行组合,来提高并行处理效率。
  • 异步操作链:使用 thenApplythenCompose 构建任务链,使代码更加简洁清晰。
  • 处理异步任务中的异常:利用 exceptionallyhandle 处理异步任务中可能发生的异常,保证系统的鲁棒性。

8. 性能注意事项

  • 使用 CompletableFuture 提供的默认线程池适合大多数场景,但在高负载或需要精细控制的场景下,最好创建自定义线程池。
  • 对于IO密集型任务,可以考虑调整线程池的大小,以便合理利用资源。

总结来说,CompletableFuture 是处理异步和并发任务的强大工具,它可以通过链式操作简化任务的组合与异常处理

posted @ 2024-09-08 22:35  Josen_Earth  阅读(36)  评论(0编辑  收藏  举报