Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Choose between ExecutorService's submit and ExecutorService's execute

People also ask

What is the difference between executor submit () and executer execute () method?

1) The submit() can accept both Runnable and Callable tasks but execute() can only accept the Runnable task. 2) The submit() method is declared in the ExecutorService interface while the execute() method is declared in the Executor interface.

What does ExecutorService submit do?

The ExecutorService interface extends Executor by adding methods that help manage and control the execution of threads. It is defined in java. util. concurrent package.

What does the execute method do?

The execute() method of ThreadPoolExecutor class executes the given task sometime in the future. The task may execute in a new thread or an existing pooled thread. If the task is not submitted to the pool due to any reason, then the task is handled by the current RejectedExecutionHandler.

What is the difference between executor and ExecutorService?

Executor just executes stuff you give it. ExecutorService adds startup, shutdown, and the ability to wait for and look at the status of jobs you've submitted for execution on top of Executor (which it extends).


There is a difference concerning exception/error handling.

A task queued with execute() that generates some Throwable will cause the UncaughtExceptionHandler for the Thread running the task to be invoked. The default UncaughtExceptionHandler, which typically prints the Throwable stack trace to System.err, will be invoked if no custom handler has been installed.

On the other hand, a Throwable generated by a task queued with submit() will bind the Throwable to the Future that was produced from the call to submit(). Calling get() on that Future will throw an ExecutionException with the original Throwable as its cause (accessible by calling getCause() on the ExecutionException).


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

From javadocs

submit(Callable<T> task)

Submits a value-returning task for execution and returns a Future representing the pending results of the task.

Future<?> submit(Runnable task)

Submits a Runnable task for execution and returns a Future representing that task.

void execute(Runnable command)

Executes the given command at some time in the future. The command may execute in a new thread, in a pooled thread, or in the calling thread, at the discretion of the Executor implementation.

You have to take precaution while using submit(). It hides exception in the framework itself unless you embed your task code in try{} catch{} block.

Example code: This code swallows Arithmetic exception : / by zero.

import java.util.concurrent.*;
import java.util.*;

public class ExecuteSubmitDemo{
    public ExecuteSubmitDemo()
    {
        System.out.println("creating service");
        ExecutorService service = Executors.newFixedThreadPool(10);
        //ExtendedExecutor service = new ExtendedExecutor();
        service.submit(new Runnable(){
                 public void run(){
                    int a=4, b = 0;
                    System.out.println("a and b="+a+":"+b);
                    System.out.println("a/b:"+(a/b));
                    System.out.println("Thread Name in Runnable after divide by zero:"+Thread.currentThread().getName());
                 }
            });
        service.shutdown();
    }
    public static void main(String args[]){
        ExecuteSubmitDemo demo = new ExecuteSubmitDemo();
    }
}

output:

java ExecuteSubmitDemo
creating service
a and b=4:0

Same code throws by replacing submit() with execute() :

Replace

service.submit(new Runnable(){

with

service.execute(new Runnable(){

output:

java ExecuteSubmitDemo
creating service
a and b=4:0
Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
        at ExecuteSubmitDemo$1.run(ExecuteSubmitDemo.java:14)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)

How to handle the these type of scenarios while using submit()?

  1. Embed your Task code ( Either Runnable or Callable implementation) with try{} catch{} block code
  2. Implement CustomThreadPoolExecutor

New solution:

import java.util.concurrent.*;
import java.util.*;

public class ExecuteSubmitDemo{
    public ExecuteSubmitDemo()
    {
        System.out.println("creating service");
        //ExecutorService service = Executors.newFixedThreadPool(10);
        ExtendedExecutor service = new ExtendedExecutor();
        service.submit(new Runnable(){
                 public void run(){
                    int a=4, b = 0;
                    System.out.println("a and b="+a+":"+b);
                    System.out.println("a/b:"+(a/b));
                    System.out.println("Thread Name in Runnable after divide by zero:"+Thread.currentThread().getName());
                 }
            });
        service.shutdown();
    }
    public static void main(String args[]){
        ExecuteSubmitDemo demo = new ExecuteSubmitDemo();
    }
}

class ExtendedExecutor extends ThreadPoolExecutor {

   public ExtendedExecutor() { 
       super(1,1,60,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(100));
   }
   // ...
   protected void afterExecute(Runnable r, Throwable t) {
     super.afterExecute(r, t);
     if (t == null && r instanceof Future<?>) {
       try {
         Object result = ((Future<?>) r).get();
       } catch (CancellationException ce) {
           t = ce;
       } catch (ExecutionException ee) {
           t = ee.getCause();
       } catch (InterruptedException ie) {
           Thread.currentThread().interrupt(); // ignore/reset
       }
     }
     if (t != null)
       System.out.println(t);
   }
 }

output:

java ExecuteSubmitDemo
creating service
a and b=4:0
java.lang.ArithmeticException: / by zero

if you dont care about the return type, use execute. it's the same as submit, just without the return of Future.


Taken from the Javadoc:

Method submit extends base method {@link Executor#execute} by creating and returning a {@link Future} that can be used to cancel execution and/or wait for completion.

Personally I prefer the use of execute because it feels more declarative, although this really is a matter of personal preference.

To give more information: in the case of the ExecutorService implementation, the core implementation being returned by the call to Executors.newSingleThreadedExecutor() is a ThreadPoolExecutor.

The submit calls are provided by its parent AbstractExecutorService and all call execute internally. execute is overridden/provided by the ThreadPoolExecutor directly.