已解决java.util.concurrent.CancellationException异常的正确解决方法,亲测有效!!!

文章目录

    问题分析

    报错原因

    解决思路

    解决方法

    总结


在Java并发编程中,Future和FutureTask是处理异步计算结果的重要工具类。然而,在使用这些工具进行并发编程时,我们可能会遇到java.util.concurrent.CancellationException异常。本异常表明因为任务被取消,导致无法检索到产生值的任务(如FutureTask)的结果。此文将深入分析CancellationException异常的原因,并提供详细的解决方案。


问题分析

CancellationException异常通常出现在尝试获取一个已经被取消的任务的结果时。在Java的并发框架中,如果一个任务正在执行或等待执行,我们可以通过调用cancel(boolean mayInterruptIfRunning)方法来取消这个任务。如果取消成功,任何后续对该任务的get()调用都将抛出CancellationException。

出现问题的场景

在多线程环境下,一个长时间运行的任务被显式取消。

调用Future.get()方法获取异步计算的结果时,如果计算任务已经被取消。

利用ExecutorService执行一组任务,并在所有任务完成之前调用shutdownNow()方法,可能会引发此异常。


报错原因

导致CancellationException的具体原因主要包括:

     1.任务被取消:当任务通过Future.cancel(true)方法被取消后,仍然尝试通过Future.get()方法获取结果。

     2.线程池关闭:当线程池通过shutdownNow()方法关闭,正在等待的或正在执行的任务将被尝试中断,进而可能导致任务取消。


解决思路

面对CancellationException异常,解决方案可从以下几个方向考虑:

      1.合理处理取消操作:正确管理任务的取消操作,只在必要时取消任务。

      2.优雅关闭线程池:使用shutdown()和awaitTermination()组合替代shutdownNow(),以更优雅地关闭线程池。

      3.异常捕获与处理:妥善捕获和处理CancellationException,避免程序异常终止。


解决方法

  • 合理处理取消操作:谨慎取消任务,确保只在确实需要取消任务以释放资源或因为用户请求停止操作时,才取消任务。
Future<?> future = executor.submit(longRunningTask);
// 基于某些条件判断是否需要取消任务
if (shouldCancel) {
    future.cancel(true);
  • 优雅关闭线程池:平滑关闭线程池,首先调用shutdown()方法停止接收新任务,然后调用awaitTermination()等待已有任务完成。
ExecutorService executor = Executors.newFixedThreadPool(10);
// 添加任务到executor
executor.shutdown(); // 停止接收新任务
try {
    if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
        executor.shutdownNow(); // 取消当前执行的任务
    }
} catch (InterruptedException ie) {
    executor.shutdownNow();
    Thread.currentThread().interrupt(); // 保留中断状态
  • 异常捕获与处理:妥善处理CancellationException,在调用Future.get()时,准备好捕获并妥善处理CancellationException
try {
    Object result = future.get();
} catch (CancellationException ce) {
    // 处理任务被取消的情况
    System.out.println("任务被取消");
} catch (InterruptedException ie) {
    Thread.currentThread().interrupt(); // 保留中断状态
} catch (ExecutionException ee) {
    // 处理任务执行过程中的异常
}

总结

通过上述步骤的实施,可以有效地解决由于任务被取消而引发的java.util.concurrent.CancellationException异常问题。在并发编程实践中,合理的任务管理和异常处理策略是保证程序稳定运行的关键。希望本文的内容对您解决相关问题提供了清晰的指导和帮助。