Engineering Full Stack Apps with Java and JavaScript
The interface ExecutorService extends Executor and provides methods to manage the lifecycle of an Executor like:
means to termination of an Executor,
methods that can produce a Future etc.
Note: A Future object can be used for tracking the progress of one or more asynchronous tasks.
Method submit extends base method Executor.execute(java.lang.Runnable) by creating and returning a Future that can be used to cancel execution and/or wait for completion.
Methods invokeAny and invokeAll execute a collection of tasks and then wait for at least one, or all, to complete, respectively.
An ExecutorService can be shut down, which will cause it to reject new tasks. The shutdown() method will allow previously submitted tasks to execute before terminating, while the shutdownNow() method prevents waiting tasks from starting and attempts to even stop currently executing tasks. Tasks submitted to an ExecutorService after it has been shut down are handled by the rejected execution handler, which might discard the task or might cause execute to throw the unchecked RejectedExecutionException.
Once all tasks have completed, the ExecutorService transitions to the terminated state. The awaitTermination(long timeout, TimeUnit unit) method blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted.
The isShutdown() and isTerminated() methods returns true if this executor has been shut down or if executor is in terminated state, respectively.
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorServiceDemo {
public void execDemo(final ExecutorService exec) {
for (int i = 0; i < 5; i++) {
Runnable task = new Runnable() {
@Override
public void run() {
try {
System.out.println("Started " +
Thread.currentThread() + " at "
+ new Date());
Thread.sleep(1000);
System.out.println("Exiting " +
Thread.currentThread() + " at "
+ new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
exec.execute(task);
}
System.out.println("Before calling shutdown. Is shutdown="
+ exec.isShutdown());
exec.shutdown();
System.out.println("After calling shutdown. Is shutdown="
+ exec.isShutdown());
}
public static void main(String[] args) {
ExecutorServiceDemo eD = new ExecutorServiceDemo();
eD.execDemo(Executors.newFixedThreadPool(2));
}
}
Here we called shutdown() after submitting all tasks and hence isShutDown() returns true, but submitted tasks are completed.
OUTPUT
Before calling shutdown. Is shutdown=false
After calling shutdown. Is shutdown=true
Started Thread[pool-1-thread-2,5,main] at Tue Jul 09 15:05:31 IST 2013
Started Thread[pool-1-thread-1,5,main] at Tue Jul 09 15:05:31 IST 2013
Exiting Thread[pool-1-thread-1,5,main] at Tue Jul 09 15:05:36 IST 2013
Started Thread[pool-1-thread-1,5,main] at Tue Jul 09 15:05:36 IST 2013
Case 1: Using shutdownNow instead of shutdown()
Replace exec.shutdown(); with exec.shutdownNow();
Here shutdownNow() will try to stop even submitted tasks by interrupting them and might result in an InterruptedException.
OUTPUT
Before calling shutdown. Is shutdown=false
After calling shutdown. Is shutdown=true
Started Thread[pool-1-thread-2,5,main] at Tue Jul 09 15:22:05 IST 2013
Started Thread[pool-1-thread-1,5,main] at Tue Jul 09 15:22:05 IST 2013
java.lang.InterruptedException: sleep interrupted
…
java.lang.InterruptedException: sleep interrupted
…
Case 2: Calling exec.shutdown(); and submitting tasks
Remove the exec.shutdownNow(); from current place and have an exec.shutdown() inside the for loop just before the end of loop.
OUTPUT
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task GenericExecutorDemo$1@7f8a8bfa rejected from java.util.concurrent.ThreadPoolExecutor@60ec0b80[Shutting down, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]
…
Started Thread[pool-1-thread-1,5,main] at Tue Jul 09 15:25:18 IST 2013
Exiting Thread[pool-1-thread-1,5,main] at Tue Jul 09 15:25:23 IST 2013
Case 3: Calling exec.shutdownNow(); and submitting tasks
Replace exec.shutdown(); with exec.shutdownNow();
Submitting tasks after shutdown are handled by rejected execution handler and might result in RejectedExecutionException. Here shutdownNow() will also try to stop the already submitted tasks by interrupting them and might result in an InterruptedException.
OUTPUT
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task ExecutorServiceDemo$1@143c8b3 rejected from java.util.concurrent.ThreadPoolExecutor
...
java.lang.InterruptedException: sleep interrupted
...