Simple threading issue

I started learning java and now I am in the chapter on concurrency. After reading something about concurrency, I tried an example of mine.

public class Task implements Runnable{ public void run() { while(!Thread.interrupted()) { try { System.out.println("task"); TimeUnit.SECONDS.sleep(2); }catch (InterruptedException e) { System.out.println("interrupted"); } } } } public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); exec.execute(new Task()); TimeUnit.SECONDS.sleep(10); exec.shutdownNow(); } 

The problem is that I expected to see the following result:

 task task task task task interrupted 

but after I get this, the program will continue to print until I close it.
So my question is what am I doing wrong? why does the program continue to print?

+6
source share
4 answers

The interrupt section in the Java tutorials on concurrency explains the problem quite well:

Interrupt Status Flag

The interrupt mechanism is implemented using an internal flag known as interrupt status. A call to Thread.interrupt sets this flag. When a thread checks for an interrupt by calling the static Thread.interrupted method, the interrupt state is cleared. The non-static method isInterrupted, which is used by one thread to request the interrupt status of another, does not change the interrupt status flag.

By convention, any method that throws an InterruptedException will clear the interrupt status when it does. However, it is always possible that the interrupt status will be immediately set again by another thread causing the interrupt.

So, when you catch InterruptedException in the loop, the interrupted status is already reset, and thus the next call to Thread.interrupted () will return false, which in turn holds the while loop. To stop the loop, you have the following options:

  • Use break to exit loop
  • Use return to exit the whole method.
  • Move the try-catch block to the outer while loop (as suggested by Nathan Hughes)
  • Aborting a call () on the current thread to set the aborted flag again
  • Use a separate logic element to control the loop and set this flag accordingly in the catch block.
  • Define the task as a recurring task using the ScheduledExecutorService and dropping the loop from your Runnable run method
+4
source

When you complete the work of the executor, he tries to stop his running tasks by interrupting them. This causes an InterruptedException to be caught, but you just swallow it and continue. You should return to the catch clause and / or reset the interrupted thread status by calling Thread.currentThread.interrupt() , which will reset the interrupted status and exit the loop.

+7
source

You are still in the while loop, adding a break or some other way out of the loop.

  catch (InterruptedException e) { System.out.println("interrupted"); break; } 

Threading in Java is a kind of collaboration, you were asked to stop, but you need to be polite enough to actually do it. This allows the flow time to cleanse its affairs before its death.

As explained in detail by Simon and Amir, the condition for ending the cycle is surprisingly not enough.

+4
source

"There are no guarantees, except for better attempts to stop processing that is actively performing tasks. For example, typical implementations will be canceled with Thread.interrupt (), so if any tasks mask or cannot respond to interrupts, they will never be able to stop execution . "

source: http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow ()

+1
source

Source: https://habr.com/ru/post/894926/


All Articles