Java 中这段代码中的 ExecutorService.submit 和 ExecutorService.execute 有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18730290/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the difference between ExecutorService.submit and ExecutorService.execute in this code in Java?
提问by brain storm
I am learning to use ExectorService
to pool threads
and send out tasks. I have a simple program below
我正在学习使用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());
}
}
}
It does nothing fancy, but creates two threads
and submits 5 tasks in total. After each thread
completes its task, it takes the next one,
In the code above, I use executor.submit
. I also changed to executor.execute
. But I do not see any difference in the output. In what way are the submit
and execute
methods different?
This what the API
says
它没有什么特别的,但是创建了两个threads
并总共提交了 5 个任务。每个thread
完成它的任务后,它需要下一个,在上面的代码中,我使用executor.submit
. 我也改成executor.execute
。但我看不出输出有什么不同。submit
和execute
方法有什么不同?这就是API
所说的
Method submit extends base method Executor.execute(java.lang.Runnable) by creating and returning a Future that can be used to cancel execution and/or wait for completion. Methods invokeAny and invokeAll perform the most commonly useful forms of bulk execution, executing a collection of tasks and then waiting for at least one, or all, to complete. (Class ExecutorCompletionService can be used to write customized variants of these methods.)
方法 submit 通过创建和返回可用于取消执行和/或等待完成的 Future 来扩展基本方法 Executor.execute(java.lang.Runnable)。方法 invokeAny 和 invokeAll 执行最常用的批量执行形式,执行一组任务,然后等待至少一个或全部完成。(类 ExecutorCompletionService 可用于编写这些方法的自定义变体。)
But it's not clear to me as what it exactly means?
但我不清楚它到底意味着什么?
采纳答案by dkatzel
As you see from the JavaDoc execute(Runnable)
does not return anything.
正如您从 JavaDocexecute(Runnable)
中看到的,不返回任何内容。
However, submit(Callable<T>)
returns a Future
object which allows a way for you to programatically cancel the running thread later as well as get the T
that is returned when the Callable
completes. See JavaDoc of Futurefor more details
但是,submit(Callable<T>)
返回一个Future
对象,它允许您稍后以编程方式取消正在运行的线程以及获取完成T
时返回的对象Callable
。有关更多详细信息,请参阅JavaDoc of Future
Future<?> future = executor.submit(longRunningJob);
...
//long running job is taking too long
future.cancel(true);
Moreover,
if future.get() == null
and doesn't throw any exception then Runnable executed successfully
此外,如果future.get() == null
并且不抛出任何异常,那么 Runnable 执行成功
回答by tbodt
The difference is that execute
simply starts the task without any further ado, whereas submit
returns a Future
object to manage the task. You can do the following things with the Future
object:
不同之处在于,它execute
只是简单地启动任务,而不用任何麻烦,而submit
返回一个Future
对象来管理任务。您可以对Future
对象执行以下操作:
- Cancel the task prematurely, with the
cancel
method. - Wait for the task to finish executing, with
get
.
- 提前取消任务,使用
cancel
方法。 - 等待任务完成执行,使用
get
.
The Future
interface is more useful if you submit a Callable
to the pool. The return value of the call
method will be returned when you call Future.get
. If you don't maintain a reference to the Future
, there is no difference.
Future
如果您将 a 提交Callable
到池,则该界面会更有用。call
调用时会返回该方法的返回值Future.get
。如果您不维护对 的引用Future
,则没有区别。
回答by Preetham R U
Submit - Returns Future object, which can be used to check result of submitted task. Can be used to cancel or to check isDone etc.
Submit - 返回 Future 对象,可用于检查提交任务的结果。可用于取消或检查 isDone 等。
Execute - doesn't return anything.
执行 - 不返回任何内容。
回答by Ravindra babu
execute:
Use it for fire and forget calls
execute:
将其用于火灾和忘记电话
submit:
Use it to inspect the result of method call and take appropriate action on Future
objected returned by the call
submit:
使用它来检查方法调用的结果并对调用Future
返回的对象采取适当的行动
Major difference: Exception
handling
主要区别:Exception
处理
submit()
hides un-handled Exception
in framework itself.
submit()
隐藏Exception
在框架本身中未处理。
execute()
throws un-handled Exception
.
execute()
抛出未处理Exception
。
Solution for handling Exceptions with submit()
处理异常的解决方案 submit()
Wrap your
Callable or Runnable code in try{} catch{} block
OR
Keep
future.get() call in try{} catch{} block
OR
implement your own
ThreadPoolExecutor
and overrideafterExecute
method
包裹你的
Callable or Runnable code in try{} catch{} block
或者
保持
future.get() call in try{} catch{} block
或者
实现你自己的
ThreadPoolExecutor
和覆盖afterExecute
方法
Regarding tour other queries on
关于旅游的其他问题
调用所有:
Executes the given tasks, returning a list of Futures holding their status and results when all complete or the timeout expires, whichever happens first.
执行给定的任务,当全部完成或超时到期时,返回一个保存其状态和结果的 Futures 列表,以先发生者为准。
调用任何:
Executes the given tasks, returning the result of one that has completed successfully (i.e., without throwing an exception), if any do before the given timeout elapses.
执行给定的任务,返回已成功完成的任务的结果(即,不抛出异常),如果在给定的超时时间过去之前执行任何操作。
Use invokeAll
if you want to wait for all submitted tasks to complete.
使用invokeAll
,如果你想等待所有提交的任务来完成。
Use invokeAny
if you are looking for successful completion of one task out of N submitted tasks. In this case, tasks in progress will be cancelled if one of the tasks completes successfully.
使用invokeAny
,如果你正在寻找一个任务的圆满完成了N个提交的任务。在这种情况下,如果其中一项任务成功完成,正在进行的任务将被取消。
Related post with code example:
与代码示例相关的帖子:
Choose between ExecutorService's submit and ExecutorService's execute
回答by amarnath harish
basically both calls execute,if u want future object you shall call submit() method here from the doc
基本上两个调用都执行,如果你想要未来的对象,你应该从文档中调用 submit() 方法
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;
}
as you can see java really has no way to start a thread other than calling run() method, IMO. since i also found that Callable.call()
method is called inside run()
method. hence if the object is callable it would still call run()
method, which inturn would call call()
method
from doc.
正如你所看到的,除了调用 run() 方法,IMO 之外,java 真的没有办法启动一个线程。因为我还发现该Callable.call()
方法被称为内部run()
方法。因此,如果对象是可调用的,它仍然会调用run()
方法,而call()
方法又会从 doc调用方法。
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
回答by amitkumar12788
A main difference between the submit() and execute() method is that ExecuterService.submit()can return result of computation because it has a return type of Future, but execute() method cannot return anything because it's return type is void. The core interface in Java 1.5's Executor framework is the Executor interface which defines the execute(Runnable task) method, whose primary purpose is to separate the task from its execution.
submit() 和 execute() 方法的主要区别在于,ExecuterService.submit() 可以返回计算结果,因为它的返回类型为 Future,而 execute() 方法不能返回任何内容,因为它的返回类型为 void。Java 1.5 Executor 框架中的核心接口是Executor 接口,它定义了execute(Runnable task) 方法,其主要目的是将任务与其执行分离。
Any task submitted to Executor can be executed by the same thread, a worker thread from a thread pool or any other thread.
任何提交给 Executor 的任务都可以由同一个线程、线程池中的工作线程或任何其他线程执行。
On the other hand, submit() method is defined in the ExecutorService interface which is a sub-interface of Executor and adds the functionality of terminating the thread pool, along with adding submit() method which can accept a Callable task and return a result of computation.
另一方面,在Executor的子接口ExecutorService接口中定义了submit()方法,增加了终止线程池的功能,同时增加了submit()方法,可以接受Callable任务并返回结果的计算。
Similarities between the execute() and submit() as well:
execute() 和 submit() 之间也有相似之处:
- Both submit() and execute() methods are used to submit a task to Executor framework for asynchronous execution.
- Both submit() and execute() can accept a Runnable task.
- You can access submit() and execute() from the ExecutorService interface because it also extends the Executor interface which declares the execute() method.
- submit() 和 execute() 方法都用于将任务提交给 Executor 框架进行异步执行。
- submit() 和 execute() 都可以接受 Runnable 任务。
- 您可以从 ExecutorService 接口访问 submit() 和 execute() 因为它也扩展了声明 execute() 方法的 Executor 接口。
Apart from the fact that submit() method can return output and execute() cannot, following are other notable differences between these two key methods of Executor framework of Java 5.
除了 submit() 方法可以返回输出而 execute() 不能返回这一事实之外,以下是 Java 5 Executor 框架的这两个关键方法之间的其他显着差异。
- The submit() can accept both Runnable and Callable task but execute() can only accept the Runnable task.
- The submit() method is declared in ExecutorService interface while execute() method is declared in the Executor interface.
- The return type of submit() method is a Future object but return type of execute() method is void.
- submit() 可以接受 Runnable 和 Callable 任务,但 execute() 只能接受 Runnable 任务。
- submit() 方法在 ExecutorService 接口中声明,而 execute() 方法在 Executor 接口中声明。
- submit() 方法的返回类型是 Future 对象,而 execute() 方法的返回类型是 void。
回答by Koray Tugay
If you check the source code, you will see that submit
is sort of a wrapper on execute
如果您检查源代码,您会发现它submit
有点像execute
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}