目录
一、Future
概念解析
Future
是Java并发包(java.util.concurrent
)中的一个重要接口,它代表异步计算的结果。在异步计算模型中,Future
作为异步任务结果的占位符和查询器,提供了以下功能:
-
占位符:当一个异步任务(通常是通过
ExecutorService
提交的Runnable
或Callable
任务)开始执行后,会返回一个与该任务关联的Future
对象。这个Future
对象如同一个“承诺”,表示未来某个时刻将产生一个计算结果。 -
查询器:通过
Future
对象,可以查询异步任务的执行状态(如是否已完成、是否已取消),并最终获取计算结果。Future
接口提供了相应的方法,如isDone()
、isCancelled()
和get()
,供客户端代码监视任务进展并访问结果。
方法详解
get()方法
get()
方法是Future
接口的核心方法,用于获取异步任务的计算结果。根据是否指定超时时间,get()
方法有两种模式:
同步获取结果:调用无参的get()
方法时,如果任务尚未完成,当前线程将阻塞等待任务完成。一旦任务完成,方法返回计算结果。如果任务抛出异常,get()
方法将该异常封装为ExecutionException
抛出。
示例代码:
Future<Integer> future = executor.submit(() -> {
// 执行耗时任务并返回结果
return someComputation();
});
try {
Integer result = future.get(); // 阻塞等待任务完成,返回结果
System.out.println("Result: " + result);
} catch (InterruptedException e) {
// 当前线程被中断,通常需要重新设置中断状态并处理中断逻辑
Thread.currentThread().interrupt();
// ...
} catch (ExecutionException e) {
// 处理任务执行期间抛出的异常
Throwable cause = e.getCause();
System.out.println("Task failed with exception: " + cause.getMessage());
}
超时获取结果:调用带超时参数的get(long timeout, TimeUnit unit)
方法时,如果任务在指定时间内完成,方法返回计算结果。若超时后任务仍未完成,方法将抛出TimeoutException
。若任务在等待期间抛出异常,get()
方法将该异常封装为ExecutionException
抛出。
示例代码:
Future<Integer> future = executor.submit(() -> {
// 执行耗时任务并返回结果
return someComputation();
});
try {
Integer result = future.get(5, TimeUnit.SECONDS); // 最多等待5秒,然后返回结果或抛出异常
System.out.println("Result: " + result);
} catch (InterruptedException e) {
// 当前线程被中断,通常需要重新设置中断状态并处理中断逻辑
Thread.currentThread().interrupt();
// ...
} catch (ExecutionException e) {
// 处理任务执行期间抛出的异常
Throwable cause = e.getCause();
System.out.println("Task failed with exception: " + cause.getMessage());
} catch (TimeoutException e) {
System.out.println("Task timed out");
}
cancel()方法
cancel()
方法用于尝试取消关联的异步任务。根据参数mayInterruptIfRunning
的不同值,取消分为两种模式:
-
正常取消:当
mayInterruptIfRunning
为false
时,如果任务尚未开始执行或已经完成,任务将被取消。如果任务正在执行,取消操作将不会中断任务,仅标记任务为已取消。后续调用isCancelled()
将返回true
,但任务仍会继续执行至完成。 -
强中断:当
mayInterruptIfRunning
为true
时,除了上述正常取消的行为外,如果任务正在执行,系统将试图中断执行任务的线程。这通常通过调用线程的interrupt()
方法实现。被中断的任务可以选择响应中断,提前结束执行。示例代码:
Future<Integer> future = executor.submit(() -> {
// 执行耗时任务并返回结果
return someComputation();
});
// 尝试取消任务,允许中断正在运行的任务
boolean cancelled = future.cancel(true);
if (cancelled) {
System.out.println("Task was cancelled");
} else {
System.out.println("Task could not be cancelled");
}
Future与ExecutorService配合使用
下面的示例展示了如何使用Future
对象与ExecutorService
结合,实现对异步任务的提交、取消、结果获取等操作:
ExecutorService executor = Executors.newFixedThreadPool(5);
// 提交一个异步任务
Future<Integer> future = executor.submit(() -> {
// 执行耗时任务并返回结果
return someComputation();
});
// 在主线程中进行其他操作...
// 查询任务是否已完成
if (future.isDone()) {
System.out.println("Task has completed");
}
// 尝试取消任务,允许中断正在运行的任务
boolean cancelled = future.cancel(true);
if (cancelled) {
System.out.println("Task was cancelled");
} else {
System.out.println("Task could not be cancelled");
}
try {
// 超时5秒后获取结果,若超时则抛出TimeoutException
Integer result = future.get(5, TimeUnit.SECONDS);
System.out.println("Result: " + result);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
// 处理异常
System.out.println("Failed to retrieve task result: " + e.getMessage());
}
// 关闭ExecutorService
executor.shutdown();
通过这样的方式,开发者可以利用Future
接口有效地管理异步任务,监控任务状态,及时获取计算结果,甚至在必要时取消任务,实现对异步计算流程的灵活控制。