1

Maybe, it is a duplicate question of Thread.isInterrupted doesn't work, Thread.interrupted does. But since I use a quite different way to call Thread.isInterrupted() and have upgraded to a newer jdk, I just think this may be caused another kind of problem.

There are three threads (not including the main thread) in my program.

  • a sleep thread sleeps for 10 seconds;
  • a checker thread checks if the sleep is interrupted by another thread;
  • an interrupter interrupts the sleep thread as long as it's started.

And here is my program:

package foobar;

public class Foobar {

    public static void main(String[] args) throws Exception {
        Thread sleep = new Thread(new Sleep());
        sleep.start();

        Thread checker = new Thread(new InterruptedChecker(sleep));
        checker.start();

        Thread interrupter = new Thread(new Interrupter(sleep));
        interrupter.start();
    }
}

class InterruptedChecker implements Runnable {

    private final Thread thread;

    InterruptedChecker(Thread thread) {
        this.thread = thread;
    }

    @Override
    public void run() {
        while (true) {
            if (thread.isInterrupted()) {
                break;
            }
        }
        System.out.println("The thread is interrupted.");
    }
}

class Sleep implements Runnable {

    @Override
    public void run() {
        try {
            Thread.sleep(10 * 1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

class Interrupter implements Runnable {

    private final Thread thread;

    Interrupter(Thread thread) {
        this.thread = thread;
    }

    @Override
    public void run() {
        System.out.println("interrupting...");
        thread.interrupt();
    }
}

The interesting thing is that somethings (quite a lot) the program keeps running and doesn't print the message "The thread is interrupted." which means that the sleep.isInterrupted() returns false, but somethings it does.

Here is the java -version of my pc (Ubuntu 13.10 64bit):

java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)

After I read Thread.isInterrupted doesn't work, Thread.interrupted does above, I tried to compile my code in a different machine using an older jdk and it worked.

And, here is the java -version of the machine (Red Hat Enterprise Linux AS release 4 (Nahant Update 3) 64bit):

java version "1.6.0_06"
Java(TM) SE Runtime Environment (build 1.6.0_06-b02)
Java HotSpot(TM) 64-Bit Server VM (build 10.0-b22, mixed mode)

So my question is that:

  1. Is there something wrong in my program?
  2. If it doesn't, does the multicore cpu or the 64 bit system have something to do with this problem?

EDIT

Thanks for Peter's comment.

What problem are you trying to solve?

I just read the post as I have stated in my comment, where in the Chapter of "Don't swallow interrupts" it says that,

code higher up on the call stack can learn of the interruption and respond to it if it wants to.

So I'm not sure if the checker thread in my program acts as, what it is called here, code higher up. I just have a try to prove the post is right. But it seems that there is something wrong.

Community
  • 1
  • 1
Wenhao Ji
  • 5,121
  • 7
  • 29
  • 40

2 Answers2

3

The interrupted flag is reset as soon as it is triggered. i.e. once sleep() have been interrupted, the flag is reset to false.


EDIT

So I'm not sure if the checker thread in my program acts as, what it is called here, code higher up. I just have a try to prove the post is right. But it seems that there is something wrong.

IMHO there is nothing higher up about another thread. What you generally have in mind is something like this.

public static void main(String... ignored) throws InterruptedException, ExecutionException {
    ExecutorService es = Executors.newSingleThreadExecutor();
    Future<?> future = es.submit(new Runnable() {
        @Override
        public void run() {
            methodA();
        }
    });
    Thread.sleep(1000);
    future.cancel(true); // interrupts task.
    long start = System.nanoTime();
    try {
        future.get();
    } catch (CancellationException expected) {
        // ignored
    }
    es.shutdown();
    es.awaitTermination(1, TimeUnit.MINUTES);
    long time = System.nanoTime() - start;
    System.out.printf("Time to cancel/shutdown was %.1f milli-seconds%n",
            time / 1e6);
}

private static void methodA() { // doesn't throw any checked exception
    for (int i = 0; i < 100; i++)
        methodB();
}

private static void methodB() {
    boolean conditionWhichIsTrue = true;
    if (conditionWhichIsTrue)
        try {
            Thread.sleep(500);
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
        }
}

prints

Time to cancel/shutdown was 1.7 milli-seconds

however, if you swallow the interrupt by commenting out the Thread.currentThread().interrupt(); line this takes about 50 seconds to stop because you only interrupted one call to sleep.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    [Thread.isInterrupted()](http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#isInterrupted()) is not static. Only your second paragraph applies here: the status is cleared as soon as `sleep` is interrupted. – Holger Dec 19 '13 at 09:44
  • If I doesn't misunderstand [this post](http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html?ca=drs-), I think `Thread.currentThread().interrupt();` restores the interrupted status of `true` after it is interrupted and won't be reset. – Wenhao Ji Dec 19 '13 at 09:46
  • @PeterLawrey so why it works on another machine. Strange, isn't it? – Wenhao Ji Dec 19 '13 at 09:52
  • 1
    It depends on the thread scheduling and the state of the JIT/Optimizations whether you can notice the interrupted state for a short time or not. Keep in mind that this lag shall be as short as possible so it’s rather a sign of a *better* jdk if it is so short that you can’t notice it anymore. – Holger Dec 19 '13 at 10:02
  • 1
    @rAy You are trying to see a very short lived event in a way which has no guarantees of success or failure. This is bound to have strange behaviour. You might find that running on a different box, a different JVM or even after you have started more programs on your computer gives different results. e.g. some machines run slower for programs which are loaded higher in memory or in a different NUMA region. – Peter Lawrey Dec 19 '13 at 10:06
  • @rAy You might find the behaviour changes if you haven't run the test for as long e.g. try a milli-second or less, or with a debugger or profiler enabled. – Peter Lawrey Dec 19 '13 at 10:07
  • @Holger Is there any pattern I can follow to achieve the some function of the program above, monitoring another thread and doing something as soon as the monitored thread is interrupted? – Wenhao Ji Dec 19 '13 at 10:10
  • @rAy There is no guarentee that the interrupted thread will see that it is interrupted if it doesn't check. You appear to be trying to solve a problem in a way which is only bound to be unreliable. What problem are you trying to solve? Why can't the interrupted thread takes an action when it is interrupted? Can you take an action when the thread is finished instead? – Peter Lawrey Dec 19 '13 at 10:15
  • @PeterLawrey I've edited my question which contains the problem I'm trying to solve. – Wenhao Ji Dec 19 '13 at 10:33
  • @rAy I have added an example of why it matters. Higher up means higher up the stack, not in an unrelated thread. – Peter Lawrey Dec 19 '13 at 10:49
0

This question also bothered me for some time. After some investigation I got the answer.

When InterruptedChecker checks isInterrupted state, the Sleep thread already died. Try to add some time consuming code after Thread.currentThread().interrupt(); in Sleep class and try again.

'interrupted' status of a thread is cleared when that thread dies.

Marko Popovic
  • 3,999
  • 3
  • 22
  • 37