Why doesn't Java Thread receive interrupt flag?

420 views Asked by At

I am trying to understand interrupting threads within an ExecutorService and I can't figure out why the following MyNeverEndingRunnable class doesn't get the interrupt signal. I have a class that implements Runnable and simply prints and waits in a loop until it is interrupted:

class MyNeverEndingRunnable
    implements Runnable
{
    int count = 0;

    @Override
    public void run()
    {
        while (true)
        {
            System.out.printf("[%d]:%d\n", Thread.currentThread().getId(), ++count);
            try { Thread.sleep(5000L); } catch (Exception ignored) {}

            if (Thread.interrupted())
            {
                break;
            }
        }
    }
}

I spawn a few of these threads then call shutdownNow() on my ExecutorService which should call interrupt on each of the running threads but the below code continues to run forever:

int threadCount = 5;
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
Future[] threads = new Future[threadCount];
for (int k = 0; k < threadCount; ++k)
{
    threads[k] = executorService.submit(new MyNeverEndingRunnable());
}

Thread.sleep(20000L);

executorService.shutdownNow();
while (!executorService.isShutdown()) Thread.sleep(1000L);

Does anyone know what I am doing wrong here?

2

There are 2 answers

1
user207421 On BEST ANSWER

From the Javadoc:

InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown. [My emphasis]

NB There's nothing that actually guarantees that threads are interrupted by shutdownNow(). It just describes that as a 'typical implementation'.

Your code is a little strange. Try this:

try
{
    Thread.sleep(5000L);
}
catch (InterruptedException exc)
{
    break;
}

and remove the Thread.interrupted() test.

1
shmosel On

Read the Javadoc on Thread.sleep():

Throws: ... InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.

As soon as the exception is thrown, it's no longer interrupted. In your case, you can immediately break out of the loop and let the thread die, as @EJP suggested. But if your code doesn't have ownership of the thread (e.g. a separate method), you'll want to make sure the interruption is propagated to the caller, either by propagating the exception, or by re-interrupting:

try {
    while (true) {
        System.out.printf("[%d]:%d\n", Thread.currentThread().getId(), ++count);
        Thread.sleep(5000L);
    }
} catch (InterruptedException notIgnored)
    Thread.currentThread().interrupt();
}

Or similarly:

while (!Thread.currentThread().isInterrupted()) {
    System.out.printf("[%d]:%d\n", Thread.currentThread().getId(), ++count);
    try {
        Thread.sleep(5000L);
    } catch (InterruptedException notIgnored)
        Thread.currentThread().interrupt();
    }
}