如何立即停止使用 ExecutorService 启动的任务?

2023-11-30

我尝试了许多不同的方法来立即停止使用 ExecutorService 启动的任务,但没有成功。

Future<Void> future = executorService.submit(new Callable<Void>(
    public Void call () {
        ... do many other things here..
        if(Thread.currentThread.isInterrupted()) {
            return null;
        }
        ... do many other things here..
        if(Thread.currentThread.isInterrupted()) {
            return null;
        }
    }
));

if(flag) { // may be true and directly cancel the task
    future.cancel(true);
}

有时我需要在任务启动后立即取消任务,您可能会好奇为什么我要这样做,您可能会想象这样一个场景:用户不小心点击了“下载”按钮来启动“下载任务”,然后他立即想要取消该操作,因为这只是意外点击。

问题是调用后future.cancel(true),任务不会停止并且Thread.currentThread.isInterrupted()仍然返回false我无法知道任务是从 call() 方法内部停止的。

我正在考虑设置一个标志,例如取消=真在调用 future.cancel(true) 并在 call() 方法中不断检查该标志之后,我认为这是一个 hack,代码可能非常难看,因为用户可以同时启动多个任务。

有没有更优雅的方式来实现我想要的?

EDIT:

这真让我抓狂。我现在已经在这个问题上花了将近一天的时间了。我将尝试对我面临的问题进行更多解释。

我执行以下操作来启动 5 个任务,每个任务将启动 5 个线程来下载文件。然后我停止所有 5 个任务立即地。对于下面的所有方法调用,我启动一个线程(ExecutorService.submit(task))以使其异步,正如您可以从方法的后缀中看出的那样。

int t1 = startTaskAysnc(task1);
int t2 = startTaskAysnc(task2);
int t3 = startTaskAysnc(task3);
int t4 = startTaskAysnc(task4);
int t5 = startTaskAysnc(task5);

int stopTaskAysnc(t1);
int stopTaskAysnc(t2);
int stopTaskAysnc(t3);
int stopTaskAysnc(t4);
int stopTaskAysnc(t5);

in 启动任务Aysnc(),我只是发起一个到远程服务器的套接字连接来获取文件的大小(这肯定需要一些时间),成功获取文件大小后,我将启动 5 个线程来下载文件的不同部分。如下(代码被简化以使其更易于理解):

public void startTaskAsync(DownloadTask task) { 
    Future<Void> future = executorService.submit(new Callable<Void>(
        public Void call () {
            // this is a synchronous call
            int fileSize = getFileSize();
            System.out.println(Thread.currentThread.isInterrupted());
            ....
            Future<Void> futures = new Future<Void>[5];
            for (int i = 0; i < futures.length; ++i) {
                futures[i] = executorService.submit(new Callable<Void>(){...});
            }

            for (int i = 0; i < futures.length; ++i) {
                futures[i].get(); // wait for it to complete
            }            
        }
    ));
    synchronized (mTaskMap) {
        mTaskMap.put(task.getId(), future);
    }
}

public void stopTaskAysnc(int taskId) {
    executorService.execute(new Runnable(){
        Future<Void> future = mTaskMap.get(taskId);
        future.cancel(true);
    });
}

我注意到一种奇怪的行为,在我为所有 5 个任务调用 stopTaskAsync() 后,总会有至少一个任务被执行stopped(即 Thread.currentThread.isInterrupted() 返回 true),其他 4 个任务继续运行。

我通过设置 UncaughtExceptionHandler 尝试了您的建议,但没有任何结果。

EDIT:

这个问题在这个链接中得到了解决:无法停止使用 ExecutorService 启动的任务


嗯,javadoc of Future.cancel(boolean)说:

如果任务已经开始,则 mayInterruptIfRunning 参数决定执行此任务的线程是否应该 被中断以试图停止任务。

所以可以肯定执行任务的线程is打断了。可能发生的情况之一是

...在这里做很多其他事情..

不小心清除了Thread's interrupted状态而没有执行所需的操作 处理。如果你要放置一个断点Thread.interrupt()你可能会抓住罪犯。

我能想到的另一个选择是任务在捕获中断之前终止,因为它已完成或抛出了一些未捕获的异常。称呼Future.get()来确定这一点。无论如何,正如 asdasd 提到的,设置一个很好的做法UncaughtExceptionHandler.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何立即停止使用 ExecutorService 启动的任务? 的相关文章

随机推荐

  • python 中的 list.insert() 实际上做了什么?

    我有这样的代码 squares for value in range 1 5 squares insert value 1 value 2 print squares print squares 0 print len squares 输出
  • nvd3 堆积面积图看起来有问题如何修复?

    我的堆积面积图如下所示 我使用的数据具有相同数量的值 就像示例中一样 我使用的数据位于 http pastebin com D07hja76 除了选择器之外 我使用的代码也几乎相似 var colors d3 scale category2
  • isEqualNode 因 html 空白不同而失败

    当我使用使用不同空格的 html 字符串时 我发现 Node isEqualNode 方法出现意外行为 无论有或没有空格 html 结构都是等效的 但 innerText 属性具有不同的值 这仅用于测试目的 因此不要对 html 字符串投反
  • 您可以编写单个 FetchXML 查询来获取一对多关系吗?

    是否可以编写一个获取根实体和多个子实体的 FetchXML 查询 我能做的就是1 1 詹姆斯 伍德是正确的 获取 XML 是递 归的 因此通过使用链接实体 您可以获得所需的信息 例如 以下内容是有效的
  • 用于在 HTML 中查找类名的正则表达式

    我想用grep找出是否 何处在一堆文件中使用了 html 类 正则表达式模式不仅应该找到 p class foo 但是也 p p class foo bar foo bar 到目前为止 我能够在下面的示例中找到 class foo 但无法使
  • 如何用Java读取视频文件的第一个和最后一个64kb?

    我想使用字幕 API 它需要视频文件的第一个和最后一个 64kb 的 md5 哈希值 我知道如何执行 md5 部分 只是想知道如何获取 128kb 的数据 Python 给出了 API 的示例 但遗憾的是我不明白它 this hash fu
  • 如何正确实现 C++ 中仅由抽象基已知的对象列表的创建(和分配)?

    我应该更喜欢堆栈分配而不是堆分配 最好按值传递 特别是当你正在创建新对象时 但同时 如果您按基类返回 您的对象将被切片 or 至少通过引用而不是传递指针 虽然您无法创建引用向量 我仔细地读了这一切 现在我觉得我知道的比以前知道的少了 我对如
  • 如何有效地使用 CompletableFuture 来映射每个输入的异步任务

    我想返回包含所有键到值的映射的映射 这些值是 API 对这些键的响应 我在用CompletableFuture and Guava为了这 以下是我的尝试 是否有其他标准方法可以使用 Java 8 和线程 API 实现相同的效果 地图正在id
  • numpy 用整数增量替换元素组

    import numpy as np data np array b b b a a a a c c d d d 我需要像这样逐步用整数替换每组字符串 data np array 0 0 0 1 1 1 1 2 2 3 3 3 我正在寻找一
  • 如何输入长度超过 4095 个字符的值?

    我试图input 包含大量 JSON 粘贴的字符串 为什么我要粘贴一大堆 json 超出了我的问题范围 但是当我说我有一个不完全愚蠢的原因时 请相信我 然而 input 仅抓取粘贴的前 4095 个字符 原因见这个答案 我的代码大致如下 i
  • 使用带有position:absolute的li时,IE8不会悬停

    我有一种图像地图 我在其中使用 li 来创建元素 并将鼠标悬停在弹出的信息上 html代码是 li a href span nbsp span span class para Some text and maybe an image goe
  • Haskell 使用特定的数据构造函数过滤嵌套列表

    假设我有数据类型 data Joke Funny String Lame String 并说我有以下嵌套列表 Funny Haha Lame boo Funny Haha Lame BOO 我将如何过滤这样的嵌套列表 以便嵌套列表中包含的任
  • sqlfiddle.com 5.5.30 和 MariaDB 5.5.31 中的不同结果

    sqlfiddle http sqlfiddle com 2 9a8b3 1 从小提琴中获取结构和数据并进行查询 导入到我的 MariaDB 5 5 31 中 我得到不同的结果 sqlfiddle PID NAME LEAGUEPOINTS
  • 使用 XOR 实现 OR,AND

    我想知道我是否可以实施or and函数仅使用xor 我认为这是不可能的 但我需要证明这一点 有任何想法吗 提前致谢 您不能仅使用 XOR 来实现 OR 或 AND 门 因为它不是通用门 此外 XOR 函数无法区分其输入处的 1 1 和 0
  • 在 AngularJS 中将货币从美国转换为英国

    我尝试显示此代码 但我需要 AngularJS 自动转换货币 div default currency symbol 0 00 currency custom currency symbol 0 00 currency div 正如 And
  • LuaSocket (UDP) 未接收数据报

    我正在为我正在进行的项目尝试 LuaSocket 我选择 UDP 作为我的协议 在网上寻找文档和教程 我尝试创建一个客户端 服务器对以进行测试和学习 根据我所读到的内容 以下代码应该可以工作 然而 只有服务器似乎工作正常 客户端发送消息 但
  • C++ 继承 - 无法访问基点?

    我似乎无法使用基类作为函数参数 我是否搞乱了继承 我的主要内容如下 int some ftn Foo f some code Bar b some ftn b Bar 类以这样的方式继承自 Foo class Bar Foo public
  • Instagram API - 如何检索用户在 Instagram 上关注的人员列表

    我想知道如何检索用户在 Instagram 上关注的人员列表 假设这个特定用户是我关注的人 所以我可以在 Instagram 应用程序上访问他 她的照片和他的关注者 如何使用 Instagram API 来执行此操作 这样做合法吗 进一步开
  • 在 Powershell 中确定不同时区的夏令时状态

    PowerShell 中是否有一种巧妙的方法来确定另一个时区的过去日期是否是夏令时 情况是这样的 我们的数据库位于欧洲 时间和日期是该服务器本地的 由于欧洲和美国在不同时间开始和停止 DST 因此我需要考虑这些时间的时差 谢谢你的建议 无需
  • 如何立即停止使用 ExecutorService 启动的任务?

    我尝试了许多不同的方法来立即停止使用 ExecutorService 启动的任务 但没有成功 Future