Java 执行器:当任务完成时,如何在不阻塞的情况下收到通知?
在 Java 编程中,执行器(Executor)是一种用于执行异步任务的框架。它提供了一种方便的方式来管理和调度任务,同时还能够提供通知机制来告知任务的完成情况。当任务完成时,我们通常希望能够在不阻塞的情况下收到通知,以便继续执行其他操作或处理任务的结果。本文将介绍如何在使用 Java 执行器时实现这一目标。使用 Future 接口Java 执行器框架中的一个关键组件是 Future 接口。它代表一个异步计算的结果,并提供了一些方法来检查任务是否完成、取消任务以及获取任务的结果。通过使用 Future 接口,我们可以在任务完成后立即获取结果,而不需要阻塞等待任务的完成。下面是一个使用 Future 接口的示例代码:javaimport java.util.concurrent.*;public class ExecutorExample { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService executor = Executors.newSingleThreadExecutor(); Future future = executor.submit(() -> { // 执行一些耗时的操作 Thread.sleep(2000); return 42; }); // 检查任务是否完成 while (!future.isDone()) { System.out.println("任务尚未完成..."); Thread.sleep(500); } // 获取任务的结果 int result = future.get(); System.out.println("任务完成,结果为:" + result); executor.shutdown(); }} 在上面的示例中,我们使用了 ExecutorService 的 submit 方法来提交一个 Callable 对象作为任务,并返回一个 Future 对象。通过调用 Future 对象的 isDone 方法,我们可以检查任务是否完成。如果任务尚未完成,我们可以继续执行其他操作,而不需要阻塞等待任务的完成。当任务完成后,我们可以通过调用 Future 对象的 get 方法来获取任务的结果。使用 CompletionService 接口除了 Future 接口,Java 执行器框架还提供了 CompletionService 接口。它是一个更高级的接口,用于将任务的提交和结果的获取合并在一起。通过使用 CompletionService 接口,我们可以在任务完成时立即获取结果,而不需要手动检查每个任务的完成状态。下面是一个使用 CompletionService 接口的示例代码:javaimport java.util.concurrent.*;public class ExecutorExample { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService executor = Executors.newFixedThreadPool(5); CompletionService completionService = new ExecutorCompletionService<>(executor); for (int i = 0; i < 10; i++) { final int taskId = i; completionService.submit(() -> { // 执行一些耗时的操作 Thread.sleep(2000); return taskId; }); } for (int i = 0; i < 10; i++) { Future future = completionService.take(); int result = future.get(); System.out.println("任务 " + result + " 完成"); } executor.shutdown(); }} 在上面的示例中,我们使用了 ExecutorService 的 newFixedThreadPool 方法创建了一个固定大小的线程池,并使用 ExecutorCompletionService 对象包装该线程池。通过调用 CompletionService 对象的 submit 方法,我们可以提交任务,并立即获得一个 Future 对象。通过调用 CompletionService 对象的 take 方法,我们可以获取已完成的任务的 Future 对象,从而获取任务的结果。在使用 Java 执行器时,我们可以通过使用 Future 接口或 CompletionService 接口来实现在任务完成时在不阻塞的情况下收到通知。通过这些接口,我们可以更好地管理和调度异步任务,并及时获取任务的结果。以上是两种常用的实现方式,根据实际需求选择合适的方式来处理任务的完成通知。