0

For some reason, when iterating over a list of threads and interrupting all of them, none of them executes the catch block with InterruptedException.

In the following repository: https://github.com/ranisalt/LiuThread

I have two threads, each of them has executor services and one of them holds readers, the other reads writers. Writers should spawn every 100 ms, write to the buffer and quit/stop/whatever just don't write again. Readers are 4 threads that try to read and, if they can, they should quit too, so there's space for another reader.

I have 100 of each (reader and writer) and if they fail to read or write, they wait 60 seconds.

Then, I have a coordinator thread that keeps testing if the buffer is empty (and interrupts the writers) or full (interrupts the readers), so they never should get to wait 60s. The buffer knows its state.

The problem is, for some reason, this snippet:

for (ThreadAzul azul : threadsAzuis) {
    azul.interrupt();
}

Is NOT interrupting the thread! I have used println to see if is getting interrupted:

try {
    sleep(60000);
    System.out.println(this.getName() + " foi dormir");
} catch (InterruptedException e) {
    System.out.println(this.getName() + " foi interrompido");
}

But this NEVER gets written. What is the reason for interrupt() not making the catch block execute?

ranieri
  • 2,030
  • 2
  • 21
  • 39
  • I've also have problems in the past using `System.out.println()` in threads for debugging, maybe concurrency and flushing issues? try `System.out.flush()` after `System.out.println(this.getName() + " foi interrompido");` – morgano May 07 '14 at 11:19
  • @morgano this is not the problem, they are sleeping correctly, but the sleep does not get interrupted. – ranieri May 07 '14 at 11:27

3 Answers3

4

Inside the main method you are invoking run() on your Thread so you never start a new Thread but instead run its code within the initial main thread. So invoking interrupt on the Thread instance you never have started will not interrupt the main thread which is actually executing the code.

The same error repeats when you submit a Thread instance to an Executor. The executor will execute the run method of the Thread instance because Thread implements Runnable but the Executor will do so within its own managed Thread but not within the Thread represented by the instance you have created but never started.

So again, invoking interrupt on the Thread instance you never have started will not interrupt the thread actually executing the code.

Generally you should not mix Thread and Executor usage. Decide for one way, dealing with Threads manually or using ExecutorSevices.

And when you are using Threads you must start them using the start() method, not invoking the run() method.

Holger
  • 285,553
  • 42
  • 434
  • 765
2

Threads only get interrupted during interruptible operations, for example Thread.sleep(), Thread.wait(), and some I/O calls (not all).

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Yes, I'm trying to interrupt a sleeping thread. This "buffer" is actually just a singleton object controlled by the coordinator. – ranieri May 07 '14 at 11:28
  • @EJP, not technically true: A thread can be interrupted at _any_ time. When it is interrupted it sets a flag (always) and it throws an InterruptedException _iff_ it was blocked in a wait-like method call. If you want to use interruption to get the attention of a long-running thread, then the thread must periodically check the flag. The purpose of the exception is only to give the thread a _chance_ to check the flag if it happens to be sleeping at the time. – Solomon Slow May 07 '14 at 14:54
1

Setting the interruptionflag, does not interrupt the Thread. The Thread just ends when it checks, if it is supposed to end. So just give the Thread the chance to check isInterrupted(), or interrupt it while it is sleeping or waiting. If you have a long-term method in run(), interrupt() will not work. You have to implemet a regularly check or another workaround.

Laufwunder
  • 773
  • 10
  • 21