Java Thread - 奇怪的 Thread.interrupted() 和 future.cancel(true) 行为

发布于 2024-08-18 15:03:09 字数 1004 浏览 6 评论 0原文

我想管理我的 TaskExecutor 返回的 Futures 对象列表。
我有这样的

 List<Future<String>> list 

 void process(ProcessThis processThis) {     
    for ( ...) {
       Future<String> future = taskExecutor.submit(processThis);
       list.add(future)
    }
 }


 void removeFutures() {
    for(Future future : list) {
       assert future.cancel(true);
 }

ProcessThis 是一个实现 Callable< 的任务字符串>并检查 Thread.interrupted() 状态

    public String call() {
        while (true) {
            if (Thread.interrupted()) {
                break;
            }
            doSomething();
        }
    }

现在的问题是,当调用 Thread.interrupted() 时,只有一部分并发线程返回“true”。
对于每个被删除的 future,removeFutures() 中的断言都会返回 true(我还检查了 isDone() 和 isCompleted()。
被中断的线程数量是随机的。超过 15 个正在运行的线程,有时 13 个被中断,有时 2 个...
我实在不明白问题出在哪里。如果我调用 future.cancel(true) 并且返回 true...然后我检查 Thread.interrupted (仅调用一次),我希望它也返回 true。
知道我错过了什么吗?

我正在构建 java 1.6.0_02-b05

I want to manage a list of Futures objects returned by my TaskExecutor.
I've something like this

 List<Future<String>> list 

 void process(ProcessThis processThis) {     
    for ( ...) {
       Future<String> future = taskExecutor.submit(processThis);
       list.add(future)
    }
 }


 void removeFutures() {
    for(Future future : list) {
       assert future.cancel(true);
 }

ProcessThis is a task that implements Callable< String> and checks for Thread.interrupted() status

    public String call() {
        while (true) {
            if (Thread.interrupted()) {
                break;
            }
            doSomething();
        }
    }

Now the problem is that only a subset of the concurrent Threads is returning 'true' when Thread.interrupted() is called.
The assert in removeFutures() returns true for every future that is removed (I checked isDone() and isCompleted() as well.
The number of Threads that are interrupted is random. Over 15 running Threads sometimes 13 are interrupted, sometimes 2 ...
I really don't understand where's the issue. if I call future.cancel(true) and this returns true... and then I check Thread.interrupted (this is called only once), I expect this to return true as well.
Any idea of what am I missing?

I'm on build java 1.6.0_02-b05

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

○闲身 2024-08-25 15:03:09

请注意,Thread.interrupted() 返回当前中断状态,然后将其清除,因此所有将来的调用都将返回 false。您想要的可能是 Thread.currentThread().isInterrupted() 。

另请注意,如果任务已完成或取消,future.cancel(true) 通常只会返回 false。如果它返回 true,则不能保证任务实际上会被取消。

doSomething() 中发生了什么?由于中断,RuntimeException 可能会在某个地方逃逸。您是否有 UncaughtExceptionHandler 设置?如果没有,您需要传递 ThreadFactory Executor,它将设置异常处理程序并记录任何错过的异常。

Be aware that Thread.interrupted() returns the current interrupted status and then clears it, so all future invocations will return false. What you want is probably Thread.currentThread().isInterrupted().

Also be aware that future.cancel(true) will usually only return false if the task had already been completed or canceled. If it returns true, that is no guarantee that the task will actually be canceled.

What is happening in doSomething()? Its possible that a RuntimeException is escaping somewhere due to the interrupt. Do you have an UncaughtExceptionHandler set? If not, you'll need to pass a ThreadFactory to the Executor that will set the exception handler and log any missed exceptions.

假装爱人 2024-08-25 15:03:09

至少,你应该恢复中断标志以使taskExecutor知道线程中断:

public String call() { 
    while (true) { 
        if (Thread.interrupted()) { 
            Thread.currentThread().interrupt();
            break; 
        } 
        doSomething(); 
    } 
} 

At least, you should restore the interruption flag to make taskExecutor aware of the thread interruption:

public String call() { 
    while (true) { 
        if (Thread.interrupted()) { 
            Thread.currentThread().interrupt();
            break; 
        } 
        doSomething(); 
    } 
} 
寄风 2024-08-25 15:03:09

一个潜在的问题是中断经常被吞掉。因此,在 doSomething() 深处(甚至在类加载中),中断可能会被例如 wait() 捕获,然后被“粗心”的代码丢弃。在我看来,中断是邪恶的。

可能值得检查所有任务在取消时是否实际上正在运行。

A potential problem that interrupts are often swallowed. So somewhere deep in doSomething() (or even in class loading), an interrupt may be caught by, say, wait() and then discarded by 'careless' code. Interrupts are evil, IMO.

It may be worth checking that all of you tasks are actually running at the time of the cancel.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文