Java
ExecutorService
submit vs execute
multithreading
concurrent programming

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 Runnable object and doesn’t support Callable. This implies that if you need a task to return a result or potentially throw a checked exception, you cannot use execute.
  • Exception Handling: Any RuntimeException thrown 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 the Runnable).
java
1ExecutorService executor = Executors.newFixedThreadPool(1);
2executor.execute(new Runnable() {
3    public void run() {
4        System.out.println("Task executed using execute()");
5    }
6});

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 Future object allowing further operations like checking if the task is completed, awaiting its result, or cancelling it.
  • Flexible Parameters: Accepts both Runnable and Callable. Thus, if you need to fetch results from a task or handle exceptions distinctly, submit is the way to go.
  • Exception Handling: If a task throws an exception, this exception is encapsulated inside the Future returned by submit. You can handle it in a controlled manner using Future.get(), which will throw an ExecutionException.
java
1ExecutorService executor = Executors.newFixedThreadPool(1);
2Future<String> future = executor.submit(new Callable<String>() {
3    public String call() {
4        return "Task executed using submit()";
5    }
6});
7
8try {
9    String result = future.get(); // fetching the result
10    System.out.println(result);
11} catch (InterruptedException | ExecutionException e) {
12    e.printStackTrace();
13}

Key Differences Summary

Featureexecute Methodsubmit Method
Return TypevoidFuture<V>
Accepted Task TypeRunnableRunnable and Callable
Exception HandlingUnhandled exceptions bubble up the call stackExceptions are encapsulated in the Future
Result RetrievalNot possiblePossible via Future.get()
Task CancellationNot directly possibleCan 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.


Course illustration
Course illustration

All Rights Reserved.