如果返回值与我无关,我应该如何在ExecutorService的提交或执行之间做出选择?

如果我对两者都进行测试,除了返回值之外,我没有看到两者之间有任何差异。

ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.execute(new Task());

ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.submit(new Task());

当前回答

摘自Javadoc:

方法submit通过创建和扩展基方法{@link Executor#execute} 返回一个{@link Future},可用于取消执行和/或等待 完成。

就我个人而言,我更喜欢使用execute,因为它感觉更具有声明性,尽管这确实是个人偏好的问题。

为了提供更多信息:在ExecutorService实现的情况下,通过调用Executors.newSingleThreadedExecutor()返回的核心实现是一个ThreadPoolExecutor。

提交调用由其父AbstractExecutorService提供,所有调用都在内部执行。execute由ThreadPoolExecutor直接覆盖/提供。

其他回答

摘自Javadoc:

方法submit通过创建和扩展基方法{@link Executor#execute} 返回一个{@link Future},可用于取消执行和/或等待 完成。

就我个人而言,我更喜欢使用execute,因为它感觉更具有声明性,尽管这确实是个人偏好的问题。

为了提供更多信息:在ExecutorService实现的情况下,通过调用Executors.newSingleThreadedExecutor()返回的核心实现是一个ThreadPoolExecutor。

提交调用由其父AbstractExecutorService提供,所有调用都在内部执行。execute由ThreadPoolExecutor直接覆盖/提供。

如果你不关心返回类型,使用execute。它和submit一样,只是没有Future的返回。

在异常/错误处理方面有区别。

使用execute()排队的任务生成一些Throwable,将导致运行该任务的线程的UncaughtExceptionHandler被调用。默认的UncaughtExceptionHandler,它通常将Throwable堆栈跟踪打印到System。如果没有安装自定义处理程序,则将调用。

另一方面,由使用submit()排队的任务生成的Throwable将绑定到调用submit()生成的Future。在该Future上调用get()将抛出一个ExecutionException,其原因为原始Throwable(通过在ExecutionException上调用getCause()来访问)。

来自Javadoc:

该命令可以在新线程、池线程或调用线程中执行,由Executor实现自行决定。

因此,根据Executor的实现,您可能会发现提交线程在任务执行时阻塞。

execute:用于火灾和忘记呼叫

submit:使用它来检查方法调用的结果,并对调用返回的Future对象采取适当的操作

从javadoc

提交(调用< T >任务)

提交一个值返回任务以执行并返回一个Future 表示任务的挂起结果。

未来的< ?> submit(可运行任务)

提交一个可运行任务以供执行,并返回表示该任务的Future 的任务。

void execute(Runnable command)

在将来的某个时间执行给定的命令。该命令可以在新线程、池线程或调用线程中执行,由Executor实现自行决定。

在使用submit()时必须采取预防措施。除非你在try{} catch{}块中嵌入你的任务代码,否则它会在框架本身中隐藏异常。

算术异常:/ by 0。

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

输出:

java ExecuteSubmitDemo
creating service
a and b=4:0

用execute()替换submit()会抛出相同的代码:

取代

service.submit(new Runnable(){

with

service.execute(new Runnable(){

输出:

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)

在使用submit()时如何处理这些类型的场景?

用try{} catch{}块代码嵌入任务代码(Runnable或Callable实现) 实现CustomThreadPoolExecutor

新的解决方案:

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);
   }
 }

输出:

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