Choose between ExecutorService's submit and ExecutorService's execute
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
In Java's concurrent programming, the ExecutorService plays a pivotal role by decoupling task submission from the mechanics of how each task will be run. As developers leverage the power of concurrent execution, they frequently encounter two pivotal methods: submit and execute. Each method serves the purpose of submitting tasks to an ExecutorService, yet they come with differences that determine their use in specific scenarios.
Core Differences between submit and execute
Execute Method
The execute method in ExecutorService is inherited from the Executor interface. Its primary purpose is to execute a given task at some point in the future and it doesn’t return any value.
Characteristics of execute:
- Void Return: It returns no value.
- Runnable Parameter: Only accepts a
Runnableobject and doesn’t supportCallable. This implies that if you need a task to return a result or potentially throw a checked exception, you cannot useexecute. - Exception Handling: Any
RuntimeExceptionthrown during execution will cause the executing thread to terminate, which will eventually bubble up to the uncaught exception handlers. It doesn’t allow for programmatic handling of exceptions within the worker itself (except by using try-catch inside theRunnable).
Submit Method
The submit method, on the other hand, is a more versatile option. It provides a future that can be used to retrieve the result of the task.
Characteristics of submit:
- Return Value: Returns a
Futureobject allowing further operations like checking if the task is completed, awaiting its result, or cancelling it. - Flexible Parameters: Accepts both
RunnableandCallable. Thus, if you need to fetch results from a task or handle exceptions distinctly,submitis the way to go. - Exception Handling: If a task throws an exception, this exception is encapsulated inside the
Futurereturned bysubmit. You can handle it in a controlled manner usingFuture.get(), which will throw anExecutionException.
Key Differences Summary
| Feature | execute Method | submit Method |
| Return Type | void | Future<V> |
| Accepted Task Type | Runnable | Runnable and Callable |
| Exception Handling | Unhandled exceptions bubble up the call stack | Exceptions are encapsulated in the Future |
| Result Retrieval | Not possible | Possible via Future.get() |
| Task Cancellation | Not directly possible | Can be canceled using Future.cancel() |
Use Cases
When to Use execute:
- Fire-and-Forget Tasks: If you don't need to return a result or handle exceptions in detail, and the task is a simple operation that needs no interaction.
- Simpler Concurrency Control: Suitable for operations where monitoring state is less critical.
When to Use submit:
- Fetching Results: If the task’s result is critical for further computations or decisions.
- Heavy Exception Handling: When exceptions need to be cleanedly handled or logged.
- Complex Task Management: You need advanced control over the life cycle of tasks, such as cancellation.
Additional Considerations
Performance Implications
The choice between execute and submit may have performance implications. Because submit inherently involves the creation of Future objects, which injects a slight overhead compared to execute. Thus, for highly optimized, performance-critical systems where task results are not necessary, execute might be favored.
Task Lifecycle Control
While submit provides more control via Future, it increases the complexity of exception management and task lifecycle control. Always ensure that tasks submitted using submit are eventually managed with proper handling of interrupts and cancellations.
In conclusion, neither execute nor submit is superior; their use depends more on the requirements of the application context, specifically whether you need task results, complex lifecycle management, and intricate exception handling.

