在Java的代码中,ExecutorService.submit和ExecutorService.execute之间有什么区别?

我正在学习使用来汇集和发送任务。我下面有一个简单的程序ExectorServicethreads

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

它没有任何花哨的东西,但创建两个并总共提交5个任务。在每个完成其任务后,它将采用下一个任务,在上面的代码中,我使用.我也改成了.但我看不出输出有任何差异。和 方法在哪些方面有所不同?这是怎么说的threadsthreadexecutor.submitexecutor.executesubmitexecuteAPI

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

但是我不清楚它到底是什么意思?


答案 1

正如你从JavaDoc中看到的,它没有返回任何东西。execute(Runnable)

但是,返回一个对象,该对象允许您稍后以编程方式取消正在运行的线程,并在完成后获取返回的线程。请参阅未来的 JavaDoc 了解更多详情submit(Callable<T>)FutureTCallable

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

此外,如果 和 没有引发任何异常,则 Runnable 已成功执行future.get() == null


答案 2

不同之处在于,只需启动任务即可轻松完成任务,而返回一个对象来管理任务。您可以对对象执行以下操作:executesubmitFutureFuture

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

如果将 a 提交到池,则该界面会更有用。调用 时将返回该方法的返回值。如果不维护对 的引用,则没有区别。FutureCallablecallFuture.getFuture