One of the leading topics in core java nowdays is java concurrent package.
Java 5 introduced introduced java.util.concurrent package.This concurrent package provides Utility classes and framework to do all the task handling ,so this framework make us avoid write our own utility classes that otherwise we were writing to handle threads in our applicaiton.
ExecutorService : ExecutorService is a useful interface provided by the concurrency package and its similar to a thread-pool which takes tasks(Callable,Runnable) and executes them with one of the threads in the pool.
Example :
package com.kunal.concurency;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
//Using the Executors containing factory and utility methods and creating a pool of 10 Runnable
ExecutorService myService = Executors.newFixedThreadPool(10);
myService.submit(new MyThread());
myService.shutdown();
}
}
package com.kunal.concurency;
public class MyThread implements Runnable {
@Override
public void run() {
System.out.println("Hi Executor");
}
}
Output:
Hi Executor
Executors : Factory and utility methods for
if your application is started via a
To terminate the threads inside the
If you want to shut down the
Java 5 introduced introduced java.util.concurrent package.This concurrent package provides Utility classes and framework to do all the task handling ,so this framework make us avoid write our own utility classes that otherwise we were writing to handle threads in our applicaiton.
ExecutorService : ExecutorService is a useful interface provided by the concurrency package and its similar to a thread-pool which takes tasks(Callable,Runnable) and executes them with one of the threads in the pool.
Example :
package com.kunal.concurency;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
//Using the Executors containing factory and utility methods and creating a pool of 10 Runnable
ExecutorService myService = Executors.newFixedThreadPool(10);
myService.submit(new MyThread());
myService.shutdown();
}
}
package com.kunal.concurency;
public class MyThread implements Runnable {
@Override
public void run() {
System.out.println("Hi Executor");
}
}
Output:
Hi Executor
Executors : Factory and utility methods for
Executor, ExecutorService, ScheduledExecutorService, ThreadFactory, and Callable classes defined in this
package.ExecutorService Implementations
SinceExecutorService is an interface, you need to its implementations in order
to make any use of it. The ExecutorService has the following implementation in the java.util.concurrent
package:- ThreadPoolExecutor
- ScheduledThreadPoolExecutor
Executors factory class to create ExecutorService instances too.
Here are a few examples of creating an ExecutorService:
ExecutorService executorService1 = Executors.newSingleThreadExecutor(); ExecutorService executorService2 = Executors.newFixedThreadPool(10); ExecutorService executorService3 = Executors.newScheduledThreadPool(10);
ExecutorService Usage
There are a few different ways to delegate tasks for execution to anExecutorService:
- execute(Runnable):
There is no way of obtaining the result of the executed
Runnable, if necessary. You will have to use aCallablefor that (explained in the following sections).
- submit(Runnable):The
submit(Runnable)method also takes aRunnableimplementation, but returns aFutureobject. ThisFutureobject can be used to check if theRunnableas finished executing.
Future future = executorService.submit(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
});
future.get(); //returns null if the task has finished correctly.
- submit(Callable):
The
submit(Callable)method is similar to thesubmit(Runnable)method except for the type of parameter it takes. TheCallableinstance is very similar to aRunnableexcept that itscall()method can return a result. TheRunnable.run()method cannot return a result.
TheCallable's result can be obtained via theFutureobject returned by thesubmit(Callable)method. Here is anExecutorServiceCallableexample:
Future future = executorService.submit(new Callable(){ public Object call() throws Exception { System.out.println("Asynchronous Callable"); return "Callable Result"; } }); System.out.println("future.get() = " + future.get());The above code example will output this:
Asynchronous Callable future.get() = Callable Result
- invokeAny(...):
The
invokeAny()method takes a collection ofCallableobjects, or subinterfaces ofCallable. Invoking this method does not return aFuture, but returns the result of one of theCallableobjects. You have no guarantee about which of theCallable's results you get. Just one of the ones that finish.
If one of the tasks complete (or throws an exception), the rest of theCallable's are cancelled.
Here is a code example:
ExecutorService executorService = Executors.newSingleThreadExecutor(); Set<Callable<String>> callables = new HashSet<Callable<String>>(); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 1"; } }); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 2"; } }); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 3"; } }); String result = executorService.invokeAny(callables); System.out.println("result = " + result); executorService.shutdown();This code example will print out the object returned by one of theCallable's in the given collection. I have tried running it a few times, and the result changes. Sometimes it is "Task 1", sometimes "Task 2" etc.
- invokeAll(...):
The
invokeAll()method invokes all of theCallableobjects you pass to it in the collection passed as parameter. TheinvokeAll()returns a list ofFutureobjects via which you can obtain the results of the executions of eachCallable.
Keep in mind that a task might finish due to an exception, so it may not have "succeeded". There is no way on aFutureto tell the difference.
Here is a code example:
ExecutorService executorService = Executors.newSingleThreadExecutor(); Set<Callable<String>> callables = new HashSet<Callable<String>>(); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 1"; } }); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 2"; } }); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 3"; } }); List<Future<String>> futures = executorService.invokeAll(callables); for(Future<String> future : futures){ System.out.println("future.get = " + future.get()); } executorService.shutdown();
if your application is started via a
main() method
and your main thread exits your application, the application will keep running if you have an
active ExexutorService in your application. The active threads inside this ExecutorService
prevents the JVM from shutting down.
To terminate the threads inside the
ExecutorService you call its shutdown() method.
The ExecutorService will not shut down immediately, but it will no longer accept new tasks, and
once all threads have finished current tasks, the ExecutorService shuts down. All tasks submitted
to the ExecutorService before shutdown() is called, are executed.
If you want to shut down the
ExecutorService immediately, you can call the shutdownNow()
method. This will attempt to stop all executing tasks right away, and skips all submitted but non-processed tasks.
There are no guarantees given about the executing tasks. Perhaps they stop, perhaps the execute until the end.
It is a best effort attempt.