在执行器服务的提交和执行器服务的执行之间进行选择

2022-08-31 06:11:19

如果返回的值不是我所关心的,我应该如何在执行器服务的提交执行之间进行选择?

如果我同时测试两者,除了返回值之外,我没有看到两者之间的任何差异。

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

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

答案 1

在异常/错误处理方面存在差异。

排队并生成一些任务将导致 调用正在运行的任务。默认值 (通常将堆栈跟踪打印到 )将在 未安装自定义处理程序时调用。execute()ThrowableUncaughtExceptionHandlerThreadUncaughtExceptionHandlerThrowableSystem.err

另一方面,由排队的任务生成的 将绑定到从对 的调用生成的 。调用该调用将抛出一个以原始作为其原因(可通过调用 )Throwablesubmit()ThrowableFuturesubmit()get()FutureExecutionExceptionThrowablegetCause()ExecutionException


答案 2

执行:将其用于开火并忘记呼叫

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

来自 javadocs

submit(Callable<T> task)

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

Future<?> submit(Runnable task)

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

void execute(Runnable command)

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

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

示例代码:此代码吞咽 。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();
    }
}

输出:

java ExecuteSubmitDemo
creating service
a and b=4:0

通过替换为 () 来抛出相同的代码:submit()execute

取代

service.submit(new Runnable(){

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() 时如何处理这些类型的场景?

  1. 将任务代码(可运行或可调用实现)嵌入 try{} catch{} 块代码
  2. 实现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