Both execute() and submit() methods are used to send a set of tasks to the Executor interface having a thread pool.
The Hierarchy goes like this, Java gives us an ExecutorService interface (having submit() method ) which is a sub-interface of Executor (interface), consisting of a method called execute() defined in it.
Basis | Submit Method | Execute Method |
---|---|---|
Functionality | It submits tasks to the Executor that would handle them for us | Runs the task with the main thread |
Return | It returns a future object which can be used to interrupt the thread in future | It just starts the task and returns void |
Declaration | It is declared in the ExecutorService interface | It is declared in the Executor interface |
Acceptance | It accepts both Runnable and Callable as a parameter | It expects a Runnable as a parameter |
Exception Handler | If submit throws an exception it becomes an integral part of the return value of the task | If Execute throws an exception it will go to the uncaught exception handler |
Use Case | Beneficial when thread being called requires output from the task it is executing | Execute is used most of the time when we just want to submit the task in the thread pool and don’t want to alter it further |
• execute() runs the task with the main thread.
//execute() Action ExecutorService executor = Executors.newFixedThreadPool(2); for (int i = 0; i < 5; i++) { executor.execute(someTask(i)); }
import java.util.concurrent.*; class task implements Callable<Integer>{ @Override public Integer call() throws Exception { System. out .println("Returning Integer using Callable Interface "); return 10; } } public class CollableExample { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService pool = Executors.newFixedThreadPool(1); task obj = new task(); System. out .println("Task submitted "); Future<Integer> future = pool.submit(obj); Integer result = future.get(); System. out .print("Printing using user : "); System. out .println(result); } }
Example: A simple code that would simply output the returned future object.
• submit() is used to submit tasks to the Executor that would handle them for us.
//submit in action ExecutorService executor = Executors.newFixedThreadPool(2); for (int i = 0; i < 5; i++) { executor.submit(someTask(i)); }
Seeing the above example one can say that both of these provide similar outputs but there are some subtle differences in both of their behaviors.
• submit() method returns a future object which can be used to interrupt the thread in future.
• The returned future object can be used for 2 major things:
◦ Canceling the task with cancel().
◦ Wait for the task for completion using get().
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; class Even implements Runnable { @Override public void run() { for(int i=1;i<=10;i++){ if(i%2==0){ System. out .println(Thread.currentThread().getName()+" Even "+i+","); } } } } class Odd implements Runnable{ @Override public void run() { for(int i=1;i<=10;i++){ if(i%2!=0){ System. out .println(Thread.currentThread().getName()+" Odd "+i+","); } } } } class ThreadPoolCreater{ public static void main(String[] args) { ExecutorService executorService= Executors.newFixedThreadPool(2); executorService.submit(new Even()); executorService.submit(new Odd()); executorService.shutdown(); } }
Explanation: The above program would create a Thread pool where one Thread would print even numbers and others will print odd numbers
• The submit() method is declared in the ExecutorService interface while the execute() method is declared in the Executor interface.
• execute() expects a Runnable as a parameter.
• submit() can accept both Runnable and Callable as a parameter.
• If execute() throws an exception it will go to the uncaught exception handler.
• If submit() throws an exception it becomes an integral part of the return value of the task.
• submit() method is just a wrapper around the execute().
/ / implementation of submit() in java docs. public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerException(); RunnableFuture<Void> ftask = newTaskFor(task, null); execute(ftask); return ftask; }
• execute() method just starts the task and returns void.
• submit() method returns a Future object which can be further used for manipulating the task in later stages of our business logic.
• execute() is used most of the time when we just want to submit the task in the thread pool and don’t want to alter it further.
• A Real-world use case could be sending a do-not-reply email where you do not expect a response from the user.
• Beneficial when thread being called requires output from the task it is executing.
• A real-world use case could be order confirmation after validating the response received from the payment gateway.
This article is contributed by Shiva Tiwari.
This post was last modified on December 6, 2020