首页 > 解决方案 > 停止(中断)正在运行阻塞操作的线程?

问题描述

与这个问题类似,但在细节上有所不同:中断等待阻塞操作的线程?

有一个我无法控制的 3pty 库,这个库有一个方法pressButtonAndHoldIt(long duration)。这是一种阻塞方法,这意味着如果您设置duration为 10 分钟 - 它将执行 10 分钟的操作(没有中断)。我从一个单独的线程中使用这个方法,所以我可以在“按住按钮”的同时做其他事情:

final Future<?> f = Executors.newSingleThreadExecutor().submit(() -> {
  3ptyLibrary.pressButtonAndHoldIt(Duration.ofMinutes(10).toSeconds());
});

var stuff = myOtherStuff();
//here I want to stop what was submitted in "f", e.g. "f.forceStop()"

通常myOtherStuff()需要大约 9 分钟,但有时可能需要 5 分钟,所以我想停止那个阻塞的后台进程。我怎样才能做到这一点?

请注意,这Executors.newSingleThreadExecutor().submit()只是一个示例:我可以在 java 中以任何方式创建后台线程(如果有帮助的话)。

标签: javamultithreading

解决方案


你唯一能做的就是打电话thatThreadRef.interrupt();和祈祷。

interrupt() 所做的是“提高中断标志”。这只完成了两件事:

  • 所有明确指定要查看的方法都将查看: 很容易识别 em:它们都是指定要抛出的方法InterruptedException,例如Thread.sleep. 如果在您调用它们时标志已启动,这些方法将立即返回(通过抛出 InterruptedException),而根本不会休眠。如果你在他们睡觉的时候打断线程,他们也会通过抛出它立即退出。
  • 对于所有其他情况,它只是...引发中断标志。这就是它所做的一切。

现在,第二件事并不是完全没用:一种方法可以不时地检查它并采取相应的行动,做任何看起来合适的事情(关于你应该做什么,没有多少实际的语义标准。因为只要您返回或以其他方式中断某些东西)。例如,在大多数操作系统(但不是所有操作系统)上,读取文件(指定为 throw InterruptedException)可能会阻塞,如果您中断它,通常这确实有效并中止读取,导致IOException发生。关键是,JVM 并不能保证它(嘿,如果你必须在架构和操作系统的组合爆炸上运行,你必须对保证有所了解)。

所以,这就是你的计划:祈祷这个 pressButtonAndHoldIt 能看到它。

如果没有,那么您几乎无法直接做任何事情。那时你最好的选择是,如果图书馆真的不支持它(不是通过中断也不是以任何其他方式)并且你不能编辑源代码或提供更新的拉取请求,那就是开始一个全新的JVM 中的 JVM(不容易),然后硬杀死它以尝试“中止”该阻塞操作。这本身可能不起作用(在这种情况下,这是一个非常糟糕的库,如果它在其 VM 死亡时泄漏资源)。这是一把可以杀死这种特殊蚊子的大枪,但它是你唯一拥有的。


推荐阅读