views:

499

answers:

2

The following program demonstrates the problem (latest JVM & whatnot):

public static void main(String[] args) throws InterruptedException {
    // if this is true, both interrupted and isInterrupted work
    final boolean withPrint = false;

    // decide whether to use isInterrupted or interrupted.
    // if this is true, the program never terminates.
    final boolean useIsInterrupted = true;

    ExecutorService executor = Executors.newSingleThreadExecutor();
    final CountDownLatch latch = new CountDownLatch(1);
    Callable<Void> callable = new Callable<Void>() {
        @Override
        public Void call() throws Exception {
            Random random = new Random();
            while (true) {
                if (withPrint) {
                    System.out.println(random.nextInt());
                    System.out.flush();
                }
                if (useIsInterrupted)
                {
                    if (Thread.currentThread().isInterrupted())
                        break;
                }
                else
                {
                    if (Thread.interrupted())
                        break;
                }
            }
            System.out.println("Nice shutdown");
            latch.countDown();
            return null;
        }
    };
    System.out.println("Task submitted");
    Future<Void> task = executor.submit(callable);
    Thread.sleep(100);
    task.cancel(true);
    latch.await();
    System.out.println("Main exited");
    executor.shutdown();
}
A: 

ripper234, i just ran this on my machine and it always stops no matter what value i use for the prints and which interrupts to use. I am using jdk1.6.0_16. looking at the javadoc, maybe it has something to do with the fact that interrupted() clears the (interrupted) state after each call and isInterrupted() does not. the fact that it works sometimes for jerome, always for me, and never(?) for you could indicated a difference in the jdks we are using OR the speed of our machines. if it has anything to do with the clearing of the state, that might explain the variability.

PaulP1975
+1  A: 

This looks like a known issue with multi-processor machines, mainly in 64-bit OS and java versions from 1.5 - 7.0

A DESCRIPTION OF THE PROBLEM : While running two simultaneous threads, the first thread interrupts the second one using Thread.interrupt(). The second thread tests if it has been interrupted calling the Thread.isInterrupted() method which always returns false.

This occurs on a multiprocessor PC running a 64-Bit OS (Vista and Linux). On Vista 64-Bit, this occurs when using a 64-bit JVM (all versions from 1.5 to 1.7), but does not occur when using a 32-bit JVM. On Linux 64-bit, this occurs when using a 64-bit JVM (all versions from 1.5 to 1.7) or when using a 32-bit JVM (all versions from 1.5 to 1.7).

The solution is to install the version with the fix, which is 1.6.0_16-b02 or later.

Mocky
Nice catch, but the bug's status is "resolved fixed in hs16(b04)". This is the version I'm running:java version "1.6.0_14"Java(TM) SE Runtime Environment (build 1.6.0_14-b08)Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode)
ripper234
Or perhaps I just don't understand the java version numbers. Is the bug supposed to be fixed in the JDK I have? Should I reopen it or download a new JDK?
ripper234
hs16(b04) is the hot spot version, not the JRE version. It looks like the fix is in 1.6.0_16-b02 which is later than your version, so you should download the latest version (1.6.0_17).
Mocky
@ripper234, does it work for you now?
Tomer Gabel
I moved to using an AtomicBoolean to signal the thread instead of interrupting the thread. Haven't checked if updating the JVM solves it.
ripper234