Java Concurrency - ExecutorService
ExecutorService allows users to run asynchronous tasks.
ExecutorService
ExecutorService is an Interface in java.util.concurrent package. It extends Executor interface.
Executor defines a single method execute(Runnable command). It is used to execute the submitted Runnable task.
Creating ExecutorService
Executors class provides factory methods to create ExecutorService. You can have a ExectorService with a single thread or a thread pool.
1 | ExecutorService executor = Executors.newSingleThreadExecutor(); |
Running Tasks
execute(Runnable)
execute(Runnable) method is inherited from Executor interface. It is used to execute a runnable task at some time in the future. The return type is void.
1 | ExecutorService executor = Executors.newFixedThreadPool(2); |
Sample output:
1 | Running task 0 using thread pool-1-thread-1 |
submit(Callable)
submit method can take a Runnable or Callable as argument. submit() method executes the Runnable or Callable and returns a Future. If you pass a Runnable to submit method, Future.get() will return null. If you pass a Callable to submit method, Future.get() will return the actual result of the execution.
submit(Callable) example usage
1 | ExecutorService executor = Executors.newFixedThreadPool(2); |
Sample output:
1 | Running task 1 using thread pool-1-thread-2 |
Run All tasks with invokeAll(Collection)
invoke all tasks will execute a collection of Callable tasks and return a list of Futures.
Example to run a task 100 times using 20 threads.
1 | ExecutorService executor = Executors.newFixedThreadPool(20); |
Shutdown
ExecutorService will keep the JVM running if you don’t shut it down.
shutdown() method will initiate an orderly shutdown. Once Shutdown() is called, no new tasks will be accepted. Tasks submitted before shutdown() call will not be cancelled. Once all threads are finished, ExecutorService will shutdown.
1 | executorService.shutdown(); |
shutdownNow() attemps to shutdown ExecutorService immediately and return a list of tasks that were awaiting execution. There is no guarantees all executing tasks wll be stopped.
1 | executorService.shutdownNow(); |
awaitTermination(long timeout, TimeUnit unit) will block until all tasks have completed execution after a shutdown request. Usually called after shutdown() or shutdownNow().
Example code
1 | executorService.shutdown(); |
ScheduledExecutorService
ScheduledExecutorService is an Interface that extends ExecutorService. It can schedule tasks to run after a given delay, or execute periodically.
use schedule()
method to schedule a task to run after 3 seconds
1 | ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); |
use scheduleAtFixedRate()
method to schedule at a fixed rate of 2 seconds.
1 | ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); |
Callable Interface
Callable is very similar to Runnable. It is a task that returns a result while Runnable
‘s run() method returns void.
Callable Interface Definition
1 |
|
Create a Callable
1 | Callable<String> myCallable = () -> { |
Future Interface
A Future represents the result of an asynchronous computation.
Future<V> Interface is in java.util.concurrent package.
1 | public interface Future<V> { |
get() method
get() method will block the current thread and waits for the execution to be finished. You can also add timeout to prevent long running threads. e.g. future.get(100, TimeUnit.SECONDS).
1 | String result = mycallableFuture.get(); |
get() throws InterruptedException and ExecutionException. They are both checked exceptions.
cancel() method
attempts to cancel execution of this task. You can set mayInterruptIfRunning parameter to be true so that an InterruptedException is throwed for the executing task.
1 | ExecutorService executor = Executors.newSingleThreadExecutor(); |
output:
1 | task started |