java ExecutorService 的未来任务没有真正取消
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11158454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Future task of ExecutorService not truly cancelling
提问by Ryan H
I push my Futures from a ExecutorService into a hash map. Later, I may call cancel on Futures from within the hash map. Although the result is true, I later hit breakpoints within the Callable procedure, as if the Future cancel() had no effect. I think it might be a case of two different references here (even though the reference IDs are listed as the same when breakpointing), but was wondering if some experts could chime in. Here's what the code looks like:
我将我的期货从 ExecutorService 推送到哈希映射中。稍后,我可能会从哈希映射中调用 Futures 上的取消。虽然结果是真的,但我后来在 Callable 过程中遇到了断点,就好像 Future cancel() 没有效果一样。我认为这可能是这里有两个不同引用的情况(即使在断点时引用 ID 被列为相同),但想知道是否有专家可以插话。代码如下所示:
ExecutorService taskExecutor = Executors.newCachedThreadPool();
Map <String, Future<Object>> results = new HashMap <String, Future<Object>>();
Future<Object> future = taskExecutor.submit(new MyProcessor(uid));
results.put(uid, future);
I allow processing to continue (it's a loop that submits tasks as they are passed in), and later I may attempt to cancel from an outside source by calling this method:
我允许处理继续(这是一个循环,在任务传入时提交任务),稍后我可能会尝试通过调用此方法从外部源取消:
public static synchronized boolean cancelThread(String uid) {
Future<Object> future = results.get(uid);
boolean success = false;
if (future != null) {
success = (future.isDone() ? true : future.cancel(true));
if (success)
results.remove(uid);
}
return success;
}
But I still encounter a "non-cancelled" path within MyProcessor.call() after future.cancel() is called - i.e. it's not really being cancelled.
但是在调用 future.cancel() 之后,我仍然在 MyProcessor.call() 中遇到“未取消”的路径 - 即它并没有真正被取消。
Where am I going wrong with this? Is there a better was to do this?
我哪里出错了?有没有更好的方法来做到这一点?
回答by Gray
I later hit breakpoints within the Callable procedure, as if the Future cancel() had no effect.
后来我在 Callable 过程中遇到断点,就好像 Future cancel() 没有效果一样。
Future.cancel(true)
removes a job that is in the queue and not yet running but if the job is already running it does the equivalent of Thread.interrupt()
. This sets the interrupt bit on the thread and causes any sleep()
, wait()
, and some other methods to throw InterruptedException
.
Future.cancel(true)
删除队列中尚未运行的作业,但如果作业已在运行,则执行等效于Thread.interrupt()
. 这将中断位的线程上,并导致任何sleep()
,wait()
和其他一些方法抛出InterruptedException
。
It is important to realize that it does notstop the thread. You need to actively check for the interrupt flag in your thread loop or properly handle InterruptedException
.
要认识到它确实是很重要的不停止线程。您需要主动检查线程循环中的中断标志或正确处理InterruptedException
.
See my SO answer here for more details:
有关更多详细信息,请在此处查看我的 SO 答案:
回答by Kanagavelu Sugumar
FutureTask :: boolean cancel(boolean mayInterruptIfRunning)
will perform interrupt
on current running thread.
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;
}
JavaDocsays the below for interrupt
JavaDoc说下面的interrupt
public void interrupt()
Interrupts this thread. Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.
If this thread is blocked in an I/O operation upon an interruptible channel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a ClosedByInterruptException.
If this thread is blocked in a Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.
If none of the previous conditions hold then this thread's interrupt status will be set.
Interrupting a thread that is not alive need not have any effect.
Throws: SecurityException - if the current thread cannot modify this thread
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 - 如果当前线程不能修改这个线程
To conclude; cancel of FutureTask
has only impact if the thread is blocked (in an invocation of the wait(),...) else it is developer responsibility to check Thread.currentThread().isInterrupted()
to quit; while performing non blocked operation.
总结; 取消FutureTask
只有在线程被阻塞时才会产生影响(在调用 wait(),...),否则开发人员有责任检查Thread.currentThread().isInterrupted()
退出;在执行非阻塞操作时。