ExecutorService的未来任务并未真正取消
我将Futures从ExecutorService推送到哈希映射中。 之后,我可以在哈希映射中调用取消期货。 虽然结果是正确的,但后来我在Callable过程中命中了断点,好像Future cancel()没有效果。 我认为这可能是两个不同引用的情况(即使引用ID在断点时被列为相同),但是想知道某些专家是否可以插入。这是代码的样子:
ExecutorService taskExecutor = Executors.newCachedThreadPool(); Map <String, Future> results = new HashMap <String, Future>(); Future future = taskExecutor.submit(new MyProcessor(uid)); results.put(uid, future);
我允许继续处理(这是一个在传入任务时提交任务的循环),稍后我可能会尝试通过调用此方法从外部源取消:
public static synchronized boolean cancelThread(String uid) { Future future = results.get(uid); boolean success = false; if (future != null) { success = (future.isDone() ? true : future.cancel(true)); if (success) results.remove(uid); } return success; }
但是在调用future.cancel()之后,我仍然在MyProcessor.call()中遇到“未取消”的路径 – 即它并没有真正被取消。
我哪里错了? 有没有更好的做到这一点?
我后来在Callable过程中命中了断点,好像Future cancel()没有效果。
Future.cancel(true)
删除队列中尚未运行的作业,但如果作业已在运行,则执行相当于Thread.interrupt()
。 这会在线程上设置中断位并导致任何sleep()
, wait()
和其他一些方法抛出InterruptedException
。
重要的是要意识到它不会阻止线程。 您需要在线程循环中主动检查中断标志或正确处理InterruptedException
。
有关详细信息,请参阅我的回答:
如何使用线程的id挂起线程?
FutureTask :: boolean cancel(boolean mayInterruptIfRunning)
将在当前运行的线程上执行interrupt
。
FutureTask.java public boolean cancel(boolean mayInterruptIfRunning) { if (!(state == NEW && UNSAFE.compareAndSwapInt(this, stateOffset, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED))) return false; try { // in case call to interrupt throws exception if (mayInterruptIfRunning) { try { Thread t = runner; if (t != null) t.interrupt(); ////////////HERE///////////// } finally { // final state UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); } } } finally { finishCompletion(); } return true; }
JavaDoc说下面的interrupt
public void interrupt()
中断此线程。 除非当前线程正在中断自身(始终允许),否则将调用此线程的checkAccess方法,这可能导致抛出SecurityException。
如果在调用Object类的wait(),wait(long)或wait(long,int)方法或者join(),join(long),join(long,int)的方法中阻塞了这个线程,sleep(long)或sleep(long,int),这个类的方法,然后它的中断状态将被清除,它将收到InterruptedException。
如果此线程在可中断通道上的I / O操作中被阻塞,则通道将被关闭,线程的中断状态将被设置,并且线程将收到ClosedByInterruptException。
如果此线程在Selector中被阻塞,则线程的中断状态将被设置,并且它将立即从选择操作返回,可能具有非零值,就像调用选择器的唤醒方法一样。
如果以前的条件都不成立,则将设置该线程的中断状态。
中断不活动的线程不会产生任何影响。
抛出:SecurityException – 如果当前线程无法修改此线程
总结 ; 取消FutureTask
只会影响线程被阻塞(在wait()的调用中,…)否则开发人员有责任检查Thread.currentThread().isInterrupted()
以退出; 执行非阻塞操作时。