
已解决:java.util.concurrent.CancellationException
java.util.concurrent.CancellationException 是一种常见的运行时异常,当尝试访问已取消的任务时会抛出该异常。这通常发生在使用 Future、ExecutorService 或其他并发工具类时。如果一个任务在执行过程中被取消,任何试图获取其结果的操作都会导致 CancellationException。
问题场景:
假设我们有一个多线程应用程序,其中一个任务在执行过程中被取消。当另一个线程尝试获取该任务的结果时,程序就会抛出 CancellationException。
代码片段:
ExecutorService executorService = Executors.newFixedThreadPool(1);
Future<String> futureTask = executorService.submit(() -> {
// 模拟长时间运行的任务
Thread.sleep(5000);
return "Task Completed";
});
// 取消任务
futureTask.cancel(true);
// 尝试获取任务结果
try {
String result = futureTask.get();
} catch (CancellationException e) {
System.out.println("任务被取消");
}导致 CancellationException 的常见原因包括:
Future.cancel(true) 方法主动取消任务。以下代码示例展示了在任务被取消后,仍然尝试获取其结果,从而导致 CancellationException 的情况。
ExecutorService executorService = Executors.newFixedThreadPool(1);
Future<String> futureTask = executorService.submit(() -> {
// 模拟长时间运行的任务
Thread.sleep(5000);
return "Task Completed";
});
// 取消任务
futureTask.cancel(true);
// 错误:尝试获取已取消任务的结果
try {
String result = futureTask.get();
} catch (CancellationException e) {
System.out.println("任务被取消");
}解释:
在任务被取消后,调用 futureTask.get() 会抛出 CancellationException,因为该任务的状态已经变为已取消。
要解决 CancellationException,应在获取任务结果前检查其状态,确保任务未被取消或未完成。
ExecutorService executorService = Executors.newFixedThreadPool(1);
Future<String> futureTask = executorService.submit(() -> {
// 模拟长时间运行的任务
Thread.sleep(5000);
return "Task Completed";
});
// 取消任务
futureTask.cancel(true);
// 正确:检查任务状态后再获取结果
if (!futureTask.isCancelled()) {
try {
String result = futureTask.get();
System.out.println("任务结果:" + result);
} catch (CancellationException e) {
System.out.println("任务被取消");
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("任务已取消,无法获取结果");
}Future.cancel 方法时,确保有合理的任务取消机制,以避免不必要的取消操作。CancellationException、InterruptedException 和 ExecutionException。通过以上方法和注意事项,可以有效地避免和处理 java.util.concurrent.CancellationException,提高多线程应用程序的健壮性和稳定性。