I am learning to use ExectorService
to pool threads
and send out tasks. I have a simple program below
import java.util.concurrent.Execu
The execute(Runnable command)
is the implemented method from Interface Executor
. It means just execute the command and gets nothing returned.
ExecutorService
has its own methods for starting tasks: submit
, invokeAny
and invokeAll
all of which have Callable
instances as their main targets. Though there're methods having Runnable
as input, actulaly Runnable
will be adapted to Callable
in the method. why Callable
? Because we can get a Future<T>
result after the task is submitted.
But when you transform a Runnable
to a Callable
, result you get is just the value you pass:
static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}
So, what's the point that we pass a Runnable
to submit instead of just getting the result when the task is finished? Because there's a method which has only Runnable
as parameter without a particular result.
Read the javadoc of Future
:
If you would like to use a Future for the sake of cancellability but not provide a usable result, you can declare types of the form Future<?> and return null as a result of the underlying task.
So, if you just want to execute a Runnable
task without any value returned, you can use execute()
.
if you want to run a Callable
task, or
if you want to run a Runnable
task with a specified result as the completion symbol, or
if you want to run a task and have the ability to cancel it,
you should use submit()
.
execute:
Use it for fire and forget calls
submit:
Use it to inspect the result of method call and take appropriate action on Future
objected returned by the call
Major difference: Exception
handling
submit()
hides un-handled Exception
in framework itself.
execute()
throws un-handled Exception
.
Solution for handling Exceptions with submit()
Wrap your Callable or Runnable code in try{} catch{} block
OR
Keep future.get() call in try{} catch{} block
OR
implement your own ThreadPoolExecutor
and override afterExecute
method
Regarding tour other queries on
invokeAll:
Executes the given tasks, returning a list of Futures holding their status and results when all complete or the timeout expires, whichever happens first.
invokeAny:
Executes the given tasks, returning the result of one that has completed successfully (i.e., without throwing an exception), if any do before the given timeout elapses.
Use invokeAll
if you want to wait for all submitted tasks to complete.
Use invokeAny
if you are looking for successful completion of one task out of N submitted tasks. In this case, tasks in progress will be cancelled if one of the tasks completes successfully.
Related post with code example:
Choose between ExecutorService's submit and ExecutorService's execute
If you check the source code, you will see that submit
is sort of a wrapper on execute
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
As you see from the JavaDoc execute(Runnable)
does not return anything.
However, submit(Callable<T>)
returns a Future
object which allows a way for you to programatically cancel the running thread later as well as get the T
that is returned when the Callable
completes. See JavaDoc of Future for more details
Future<?> future = executor.submit(longRunningJob);
...
//long running job is taking too long
future.cancel(true);
Moreover,
if future.get() == null
and doesn't throw any exception then Runnable executed successfully
Submit - Returns Future object, which can be used to check result of submitted task. Can be used to cancel or to check isDone etc.
Execute - doesn't return anything.
A main difference between the submit() and execute() method is that ExecuterService.submit()can return result of computation because it has a return type of Future, but execute() method cannot return anything because it's return type is void. The core interface in Java 1.5's Executor framework is the Executor interface which defines the execute(Runnable task) method, whose primary purpose is to separate the task from its execution.
Any task submitted to Executor can be executed by the same thread, a worker thread from a thread pool or any other thread.
On the other hand, submit() method is defined in the ExecutorService interface which is a sub-interface of Executor and adds the functionality of terminating the thread pool, along with adding submit() method which can accept a Callable task and return a result of computation.
Similarities between the execute() and submit() as well:
Apart from the fact that submit() method can return output and execute() cannot, following are other notable differences between these two key methods of Executor framework of Java 5.