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

问题描述 投票:42回答:7

我正在学习使用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());
        }
    }
        }

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

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

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

java multithreading threadpool executorservice
7个回答
45
投票

正如您从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);

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


43
投票

区别在于execute只是简单地启动任务,而submit返回一个Future对象来管理任务。您可以使用Future对象执行以下操作:

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

如果您向池中提交FutureCallable界面会更有用。当您调用call时,将返回Future.get方法的返回值。如果你没有保持对Future的引用,那就没有区别了。


16
投票

execute:用于火灾和忘记呼叫

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

主要区别:Exception处理

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

qazxsw poi投掷未处理的qazxsw poi。

使用execute()处理异常的解决方案

  1. 包裹你的Exception 要么
  2. 保持submit() 要么
  3. 实现自己的Callable or Runnable code in try{} catch{} block并覆盖future.get() call in try{} catch{} block方法

关于旅游其他查询

ThreadPoolExecutor

执行给定的任务,返回一个Futures列表,其中包含所有完成或超时到期时的状态和结果,以先发生者为准。

afterExecute

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

如果要等待所有提交的任务完成,请使用invokeAll

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

相关文章的代码示例:

invokeAll


5
投票

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

执行 - 不返回任何内容。


2
投票

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

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

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

execute()和submit()之间的相似之处:

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

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

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

1
投票

如果你查看源代码,你会发现invokeAnyChoose between ExecutorService's submit and ExecutorService's execute的包装器

submit

0
投票

基本上两个调用都执行,如果你想要将来的对象,你应该从doc调用submit()方法

execute

正如你所看到的,除了调用run()方法,IMO之外,java真的无法启动一个线程。因为我也发现在public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerException(); RunnableFuture<Void> ftask = newTaskFor(task, null); execute(ftask); return ftask; } 方法中调用public <T> Future<T> submit(Callable<T> task) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task); execute(ftask); return ftask; } public <T> Future<T> submit(Runnable task, T result) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task, result); execute(ftask); return ftask; } 方法。因此,如果对象是可调用的,它仍然会调用Callable.call()方法,该方法将调用doc中的run()方法。

run()
© www.soinside.com 2019 - 2024. All rights reserved.