首页 > 编程语言 >【Java】已解决:java.util.concurrent.CancellationException

【Java】已解决:java.util.concurrent.CancellationException

时间:2024-09-07 22:24:23浏览次数:11  
标签:java CancellationException 取消 获取 示例 util concurrent 任务 futureTask

文章目录


在这里插入图片描述
已解决:java.util.concurrent.CancellationException

一、分析问题背景

java.util.concurrent.CancellationException 是一种常见的运行时异常,当尝试访问已取消的任务时会抛出该异常。这通常发生在使用 FutureExecutorService 或其他并发工具类时。如果一个任务在执行过程中被取消,任何试图获取其结果的操作都会导致 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 的常见原因包括:

  1. 任务主动取消:如上述代码示例,通过调用 Future.cancel(true) 方法主动取消任务。
  2. 任务超时:如果任务超出预定时间未完成,可能会被取消。
  3. 线程中断:任务在运行过程中可能会因线程中断而被取消。
  4. 错误的任务状态检查:在获取任务结果前,没有正确检查任务的状态,导致尝试获取已取消任务的结果。

三、错误代码示例

以下代码示例展示了在任务被取消后,仍然尝试获取其结果,从而导致 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("任务已取消,无法获取结果");
}

五、注意事项

  1. 检查任务状态:在获取任务结果前,务必检查任务是否已被取消或是否已完成。
  2. 合理的任务取消机制:在使用 Future.cancel 方法时,确保有合理的任务取消机制,以避免不必要的取消操作。
  3. 异常处理:在多线程编程中,适当的异常处理至关重要。确保捕获并处理所有可能的异常,如 CancellationExceptionInterruptedExceptionExecutionException
  4. 代码风格:保持良好的代码风格和结构,便于阅读和维护。
  5. 数据类型匹配:在并发编程中,确保所有数据类型匹配,避免因数据类型不匹配引发的运行时错误。

通过以上方法和注意事项,可以有效地避免和处理 java.util.concurrent.CancellationException,提高多线程应用程序的健壮性和稳定性。

标签:java,CancellationException,取消,获取,示例,util,concurrent,任务,futureTask
From: https://blog.csdn.net/a1657054242/article/details/140365502

相关文章

  • 【Java】已解决:org.aopalliance.aop.AspectException
    文章目录一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项已解决:org.aopalliance.aop.AspectException一、分析问题背景在使用SpringAOP(面向切面编程)时,开发者有时会遇到org.aopalliance.aop.AspectException报错。这通常发生......
  • Javaweb-约束案例
    createtableemp( idintPRIMARYKEYAUTO_INCREMENT, enamevarchar(50)notnullunique, joindatedatenotnull, salarydouble(7,2)notnull, bonusdouble(7,2)default0);insertintoemp(id,ename,joindate,salary,bonus)values(1,'张三',�......
  • Zabbix02 Zabbix告警通知, 故障自愈, 主动被动模式, JAVA应用网络设备等的监控及分布
    图形Graphs#点击web端配置下的模板,选择模板对应的图形,点击右上角创建图标#输入名称TCP状态#监控项选择添加,最后点添加#点击监测下关联该模板的主机,点击图形,就能看到添加的图形#仪表盘为图形的组合#配置下模板里,点击仪表盘栏,点击创建仪表盘,构件可把之前画的图添加出......
  • Java 21的Preferences API的笔记
    JavaCoreLibrariesPreferencesAPI多用户环境下,应用程序保存配置参数的一种API,目前支持用户和系统两类配置。在现有的项目中,目前没有使用过本API。ComparingthePreferencesAPItoOtherMechanisms通常,应用的开发者还可以使用PropertiesAPI或者JNDIAPI。UsageNotes......
  • java 一个对象list 通过获取最大版本的 name值,版本为字符串格式 1 1.1 2 2.1 3
    你可以使用Java的流(Streams)功能来获取具有最大版本的name值。假设你的对象类名为Item,并且包含name和version字段,可以按照以下方式操作:importjava.util.*;importjava.util.stream.*;classItem{Stringname;Stringversion;//Constructor,getters,......
  • Java中Runtime类的学习
    Runtime类目录Runtime类什么是RuntimeRuntime类有哪些方法,有什么用什么是RuntimeRuntime(运行时),每个Java程序在运行时都相当于启动了一个JVM实例,每个JVM实例都对应一个Runtime对象。Runtime对象是由JVM负责实例化的,因此我们无法通过传统的方式实例化一个Runtime对象,只能通过调......
  • 彻底理解JavaScript中的闭包
    闭包是js的一个难点也是它的一个特色,是我们必须掌握的js高级特性,那么什么是闭包呢?它又有什么用呢?我们都知道,js的作用域分两种,全局和局部,基于我们所熟悉的作用域链相关知识,我们知道在js作用域环境中访问变量的权利是由内向外的,内部作用域可以获得当前作用域下的变量并且可以获......
  • Java基础13
    内部类将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,类B则称为外部类。 内部类的声明理由:当一个事物A的内部,有一部分需要一个完整的结构B进行描述,而这个内部结构B只为外部事物A提供服务,并不会在其他地方用到,那么整个内部的完整结构B最好使用内部类。遵循高内聚......
  • Java多线程中常见死锁问题及解决方案
    在编写Java多线程代码的时候,很难避免会出现线程安全问题,在线程安全问题中也有一个很常见的现象就是死锁现象。今天我们就来聊一聊Java中的死锁问题,以及如何避免死锁问题。本次知识点讲解建立在大家已经知道“锁”......
  • Java反序列化漏洞-TemplatesImpl利用链分析
    目录一、前言二、正文1.寻找利用链2.构造POC2.1生成字节码2.2加载字节码1)getTransletInstance2)defineTransletClasses2.3创建实例3.完整POC三、参考文章一、前言java.lang.ClassLoader#defineClassdefineClass可以加载字节码,但由于defineClass的作用域是protected,所以攻......