MST

星途 面试题库

面试题:Java 中 CompletableFuture 在高并发场景下的状态监控与资源优化

在高并发场景下,有大量基于 CompletableFuture 的异步任务同时执行。如何有效地监控这些任务的执行状态,避免因状态监控带来的性能损耗?并且,当某些任务执行失败时,如何实现优雅的资源释放与重试机制,同时保证整个系统的稳定性和高效性?请结合代码示例阐述实现思路。
36.5万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

1. 监控任务执行状态

为了有效地监控 CompletableFuture 异步任务的执行状态,同时避免性能损耗,可以利用 CompletableFuture 提供的回调方法。这些回调方法会在任务完成或失败时被调用,从而可以在不额外轮询的情况下得知任务状态。

示例代码如下:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class CompletableFutureMonitoring {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 模拟异步任务
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            return "Task completed";
        });

        future.thenApply(result -> {
            System.out.println("Task completed successfully: " + result);
            return result;
        }).exceptionally(ex -> {
            System.out.println("Task failed: " + ex.getMessage());
            return null;
        });

        try {
            // 获取任务结果(如果需要阻塞等待任务完成)
            String result = future.get();
            System.out.println("Final result: " + result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,thenApply 方法用于在任务成功完成时执行回调,exceptionally 方法用于在任务执行失败时执行回调。这样就可以实时监控任务的执行状态,而无需额外的轮询操作。

2. 资源释放与重试机制

当任务执行失败时,实现优雅的资源释放与重试机制可以通过 CompletableFuture 的链式调用以及自定义的重试逻辑来完成。

示例代码如下:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class CompletableFutureRetry {
    private static final int MAX_RETRIES = 3;

    public static void main(String[] args) {
        CompletableFuture<String> future = performTaskWithRetry(0);

        future.thenApply(result -> {
            System.out.println("Task completed successfully: " + result);
            return result;
        }).exceptionally(ex -> {
            System.out.println("All retries failed: " + ex.getMessage());
            return null;
        });

        try {
            // 获取任务结果(如果需要阻塞等待任务完成)
            String result = future.get();
            System.out.println("Final result: " + result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    private static CompletableFuture<String> performTaskWithRetry(int retryCount) {
        return CompletableFuture.supplyAsync(() -> {
            if (Math.random() < 0.5) { // 模拟 50% 的失败率
                throw new RuntimeException("Task failed");
            }
            return "Task completed";
        }).exceptionally(ex -> {
            if (retryCount < MAX_RETRIES) {
                System.out.println("Retry attempt " + (retryCount + 1) + ": " + ex.getMessage());
                return performTaskWithRetry(retryCount + 1).join();
            } else {
                throw new RuntimeException("Max retries reached", ex);
            }
        });
    }
}

在上述代码中,performTaskWithRetry 方法实现了重试逻辑。当任务失败时,如果重试次数未达到最大重试次数,会递归调用自身进行重试。同时,在任务执行过程中,如果有需要释放的资源,可以在 exceptionally 回调中进行释放操作,以保证资源的正确处理。这样可以在保证系统稳定性和高效性的同时,实现优雅的资源释放与重试机制。