What is the difference between ExecutorService.submit and ExecutorService.execute in this code in Java?

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


The difference is that execute simply starts the task without any further ado, whereas submit returns a Future object to manage the task. You can do the following things with the Future object:

  • Cancel the task prematurely, with the cancel method.
  • Wait for the task to finish executing, with get.

The Future interface is more useful if you submit a Callable to the pool. The return value of the call method will be returned when you call Future.get. If you don't maintain a reference to the Future, there is no difference.


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()

  1. Wrap your Callable or Runnable code in try{} catch{} block

    OR

  2. Keep future.get() call in try{} catch{} block

    OR

  3. 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