English 中文(简体)
Java Thread - weird Thread.interrupted() and future.cancel(true) behaviour
原标题:

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

问题回答

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.

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(); 
    } 
} 

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.





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签