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

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

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

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

原文由 brain storm 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 497
2 个回答

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

但是, submit(Callable<T>) 返回一个 Future 对象,它允许您稍后以编程方式取消正在运行的线程,并在返回 -that-that 时获取 T Callable 完成。有关详细信息,请参阅 Future 的 JavaDoc

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

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

原文由 dkatzel 发布,翻译遵循 CC BY-SA 3.0 许可协议

不同之处在于 execute 直接启动任务,而 submit 返回一个 Future 对象来管理任务。您可以使用 Future 对象执行以下操作:

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

如果您将 Callable 提交到池中, Future 界面会更有用。 call 方法的返回值将在您调用 Future.get 时返回。如果您不维护对 Future 的引用,则没有区别。

原文由 tbodt 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题