基本上我有以下片段,
(let [task (FutureTask. fn)
thr (Thread. task)]
(.start thr)
;;wait for signal...
(.cancel task true)
(.stop thr))
问题是偶尔取消不起作用,AFAICT 取消导致并引发异常,但是下面的一些代码捕获了它?有没有确定的方法可以取消未来的任务?
fn 是一个基本上执行一系列长时间运行计算的函数,因此我无法循环检查布尔标志。
基本上我有以下片段,
(let [task (FutureTask. fn)
thr (Thread. task)]
(.start thr)
;;wait for signal...
(.cancel task true)
(.stop thr))
问题是偶尔取消不起作用,AFAICT 取消导致并引发异常,但是下面的一些代码捕获了它?有没有确定的方法可以取消未来的任务?
fn 是一个基本上执行一系列长时间运行计算的函数,因此我无法循环检查布尔标志。
在 Java 中没有办法自动停止正在运行的任务——在一般情况下,简单地“杀死”正在执行的线程是不安全的,因为这样做可能会使事情处于不一致的状态。结果,这种能力被有意地排除在 Java 之外。
当您取消任务时,在执行线程中会设置一个标志,但不会引发异常。为了允许取消任务,您必须编写代码来定期检查线程是否已被中断:
while (notDone) {
if (Thread.isInterrupted()){
return; // we were cancelled (or interrupted in some other way)
}
doSomeHardWork()
}
根据我的(有限的)知识,没有通用的方法可以做到这一点。这是因为你可以有一个不可中断的远程任务,你可以有一个纯函数任务,因此可以安全地杀死,你可以有很多子任务(正如 nerdytenor 提到的——检查每个之间的 isInterrupted 状态),你可以混合一切,你可以有一个任务,当被杀死时会将其他任务置于全局锁定状态......所以据我所知,你必须自己做。
你执行什么样的计算?你能在里面做什么吗?如果整个任务即将被取消,也许创建一些全局的、线程安全的表 toInterrupt 并检查每个子任务?我知道这是非常不习惯的,但现在想不出更好的方法。
或者,如果这些确实是纯函数计算并且您对此非常确定——杀死进程/线程并希望您是对的。
这个问题可能与Executing a function with a timeout有关
该宏适用于我的代码,thunk-timeout 代码在这里
(defmacro with-timeout [time & body]
`(thunk-timeout (fn [] ~@body) ~time))