I am trying to learn the concurrency API of java. Below is a sample program.

 class WaitTest { public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException { ExecutorService executorService = null; try { executorService = Executors.newSingleThreadExecutor(); Future<?> future = executorService.submit(() -> { for (int i = 0; i < 100; i++) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Printing " + i); } }); future.get(5, TimeUnit.SECONDS); System.out.println("Reached successfully"); } finally { if (executorService != null) { executorService.shutdown(); } } } } 

The Runnable task being provided to the ExecutorService takes 10 seconds to complete. I have set a timeout of 5 seconds to get the result from the future object. So obviously the main method is exiting after 5 seconds because of the TimeoutException being thrown. But the Runnable task keeps on executing even after main method exits.

Here is the output.

Printing 0 Printing 1 Printing 2 Printing 3 Printing 4 Printing 5 Printing 6 Printing 7 Printing 8 Printing 9 Printing 10 Printing 11 Printing 12 Printing 13 Printing 14 Printing 15 Printing 16 Printing 17 Printing 18 Printing 19 Printing 20 Printing 21 Printing 22 Printing 23 Printing 24 Printing 25 Printing 26 Printing 27 Printing 28 Printing 29 Printing 30 Printing 31 Printing 32 Printing 33 Printing 34 Printing 35 Printing 36 Printing 37 Printing 38 Printing 39 Printing 40 Printing 41 Printing 42 Printing 43 Exception in thread "main" java.util.concurrent.TimeoutException at java.util.concurrent.FutureTask.get(FutureTask.java:205) at ocp.WaitTest.main(ConcurrencyTest.java:89) Printing 44 Printing 45 Printing 46 Printing 47 Printing 48 Printing 49 Printing 50 Printing 51 Printing 52 Printing 53 Printing 54 Printing 55 Printing 56 Printing 57 Printing 58 Printing 59 Printing 60 Printing 61 Printing 62 Printing 63 Printing 64 Printing 65 Printing 66 Printing 67 Printing 68 Printing 69 Printing 70 Printing 71 Printing 72 Printing 73 Printing 74 Printing 75 Printing 76 Printing 77 Printing 78 Printing 79 Printing 80 Printing 81 Printing 82 Printing 83 Printing 84 Printing 85 Printing 86 Printing 87 Printing 88 Printing 89 Printing 90 Printing 91 Printing 92 Printing 93 Printing 94 Printing 95 Printing 96 Printing 97 Printing 98 Printing 99 

Any idea ?

3

3 Answers

There are a few things going on. First, the threads used by Executors.newSingleThreadExecutor() are non-daemon threads. As the documentation of Thread mentions, non-daemon threads will keep the JVM alive.

When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class). The Java Virtual Machine continues to execute threads until either of the following occurs:

  • The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
  • All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.

Second, ExecutorService.shutdown() doesn't cancel any queued or currently executing tasks. It's merely a signal to the ExecutorService to no longer accept new tasks and to terminate once all existing tasks have completed. From the Javadoc:

Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.

This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that.

If you want to try and terminate the ExecutorService immediately you must use ExecutorService.shutdownNow().

Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.

This method does not wait for actively executing tasks to terminate. Use awaitTermination to do that.

There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.

As the Javadoc states, there is no guarantee the executing tasks will terminate even with shutdownNow. The developer must code the task to respond to interruptions.

This leads to the third thing: Your task doesn't respond to interruptions. While Thread.sleep will throw an InterruptedException when the thread is interrupted you don't break out of the loop when said exception is thrown; your code simply prints the stack trace then continues onto the next iteration. To fix this add a break statement at the end of the catch block.

You also have the option of using a custom ThreadFactory via Executors.newSingleThreadExecutor(ThreadFactory). If you have your factory return daemon threads then the JVM will exit once main returns.

0

The TimeoutException has occurred in the thread that is running the main() function, and not the thread being executed by executor service.

So although thread running the main function has completed execution, the JVM will still wait for for all other executing threads (in this case the thread that is printing numbers) to terminate.

shutdownNow() would try to interrupt the thread but you are catching interrupt exception in sleep. So you should put the whole body of your code in try catch block.

This might helps you

public class Test { public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException { ExecutorService executorService = null; try { executorService = Executors.newSingleThreadExecutor(); Future<?> future = executorService.submit(() -> { try { for (int i = 0; i < 100; i++) { Thread.sleep(100); System.out.println("Printing " + i); } } catch (Exception e) { System.out.println("Interrupted"); } }); future.get(5, TimeUnit.SECONDS); System.out.println("Reached successfully"); } finally { if (executorService != null) { executorService.shutdownNow(); } } } } 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy