Java中此代码中的ExecutorService.submit和ExecutorService.execute有什么区别?

bra*_*orm 53 java multithreading executorservice threadpool

我正在学习用来ExectorService汇集threads和发送任务.我有一个简单的程序如下

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


class Processor implements Runnable {

    private int id;

    public Processor(int id) {
        this.id = id;
    }

    public void run() {
        System.out.println("Starting: " + id);

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            System.out.println("sorry, being interupted, good bye!");
            System.out.println("Interrupted "+Thread.currentThread().getName());
            e.printStackTrace();    
        }

        System.out.println("Completed: " + id);
    }
}


public class ExecutorExample {

    public static void main(String[] args) {
        Boolean isCompleted=false;

        ExecutorService executor = Executors.newFixedThreadPool(2);

        for(int i=0; i<5; i++) {
            executor.execute(new Processor(i));
        }

        //executor does not accept any more tasks but the submitted tasks continue
        executor.shutdown();

        System.out.println("All tasks submitted.");

        try {
            //wait for the exectutor to terminate normally, which will return true
            //if timeout happens, returns false, but this does NOT interrupt the threads
            isCompleted=executor.awaitTermination(100, TimeUnit.SECONDS);
            //this will interrupt thread it manages. catch the interrupted exception in the threads 
            //If not, threads will run forever and executor will never be able to shutdown.
            executor.shutdownNow();
        } catch (InterruptedException e) {
        }

        if (isCompleted){
        System.out.println("All tasks completed.");
       }
        else {
            System.out.println("Timeout "+Thread.currentThread().getName());
        }
    }
        }
Run Code Online (Sandbox Code Playgroud)

它没有任何花哨,但创建了两个threads并总共提交了5个任务.在每个thread完成任务之后,它需要下一个,在上面的代码中,我使用executor.submit.我也换了executor.execute.但我没有看到输出有任何差异.这些submit and execute方法有何不同?这API就是说

方法submit通过创建和返回可用于取消执行和/或等待完成的Future来扩展基本方法Executor.execute(java.lang.Runnable).方法invokeAny和invokeAll执行最常用的批量执行形式,执行一组任务,然后等待至少一个或全部完成.(类ExecutorCompletionService可用于编写这些方法的自定义变体.)

但我不清楚它究竟意味着什么?

dka*_*zel 50

正如您从JavaDoc execute(Runnable)中看到的那样,不会返回任何内容.

但是,submit(Callable<T>)返回一个Future对象,该对象允许您以某种方式以编程方式取消正在运行的线程,以及获取完成后T返回的线程Callable.有关更多详细信息,请参阅JavaDoc of Future

Future<?> future = executor.submit(longRunningJob);
...
//long running job is taking too long
future.cancel(true);
Run Code Online (Sandbox Code Playgroud)

此外,如果future.get() == null并且没有抛出任何异常,则Runnable成功执行

  • 只是添加-&gt;一旦线程拿起任务就不能取消。虽然它会中断运行它的线程。 (2认同)

tbo*_*odt 44

不同之处在于,execute只需启动任务而不需要任何进一步的麻烦,而submit返回一个Future对象来管理任务.您可以使用该Future对象执行以下操作:

  • 使用该cancel方法提前取消任务.
  • 等待任务完成执行get.

Future如果您向Callable池提交,则该界面更有用.call调用时将返回方法的返回值Future.get.如果你没有保留对它的引用Future,那就没有区别了.

  • 不,execute() 规范说“在将来的某个时间执行给定的命令”。所以,它不一定立即开始。不同之处在于,您不关心它何时执行或检查结果或完成等内容。 (2认同)

Rav*_*abu 16

execute: 用它来点火和忘记电话

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

主要区别:Exception处理

submit()Exception在框架本身隐藏未处理.

execute()抛出未处理的Exception.

用于处理异常的解决方案 submit()

  1. 包裹你的 Callable or Runnable code in try{} catch{} block

    要么

  2. 保持 future.get() call in try{} catch{} block

    要么

  3. 实现自己的ThreadPoolExecutor和覆盖afterExecute方法

关于旅游其他查询

invokeAll:

执行给定的任务,返回一个Futures列表,在完成或超时到期时保持其状态和结果,以先发生者为准.

invokeAny:

执行给定的任务,返回已成功完成的任务的结果(即,不抛出异常),如果在给定的超时之前已经执行了任何操作.

使用invokeAll,如果你想等待所有提交的任务来完成.

invokeAny如果您正在寻找N个提交任务中的一个任务的成功完成,请使用.在这种情况下,如果其中一个任务成功完成,则将取消正在进行的任务.

相关文章的代码示例:

在ExecutorService的提交和ExecutorService的执行之间进行选择

  • `submit` 不会“隐藏”异常,它会在调用 `get` 时将异常包裹在 `ExecutionException` 中。然后可以通过 `ExecutionException.getCause()` 检索原始异常 (3认同)

ami*_*788 10

submit() 和 execute() 方法的主要区别在于 ExecuterService.submit() 可以返回计算结果,因为它的返回类型为 Future,而 execute() 方法不能返回任何内容,因为它的返回类型为 void。Java 1.5 Executor 框架中的核心接口是Executor 接口,它定义了execute(Runnable task) 方法,其主要目的是将任务与其执行分离。

任何提交给 Executor 的任务都可以由同一个线程、线程池中的工作线程或任何其他线程执行。

另一方面,在Executor的子接口ExecutorService接口中定义了submit()方法,增加了终止线程池的功能,同时增加了submit()方法,可以接受Callable任务并返回结果的计算。

execute() 和 submit() 之间也有相似之处:

  1. submit() 和 execute() 方法都用于将任务提交给 Executor 框架进行异步执行。
  2. submit() 和 execute() 都可以接受 Runnable 任务。
  3. 您可以从 ExecutorService 接口访问 submit() 和 execute() 因为它也扩展了声明 execute() 方法的 Executor 接口。

除了 submit() 方法可以返回输出而 execute() 方法不能返回,以下是 Java 5 Executor 框架的这两个关键方法之间的其他显着差异。

  1. submit() 可以接受 Runnable 和 Callable 任务,但 execute() 只能接受 Runnable 任务。
  2. submit() 方法在 ExecutorService 接口中声明,而 execute() 方法在 Executor 接口中声明。
  3. submit() 方法的返回类型是 Future 对象,而 execute() 方法的返回类型是 void。


Kor*_*gay 8

如果您检查源代码,您会发现它submitexecute.

java.util.concurrent.AbstractExecutorService#submit(java.lang.Runnable)
Run Code Online (Sandbox Code Playgroud)
public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

提交 - 返回Future对象,可用于检查提交任务的结果.可用于取消或检查isDone等.

执行 - 不返回任何内容.