Java 在 ExecutorService 的提交和 ExecutorService 的执行之间进行选择
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3929342/
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
Choose between ExecutorService's submit and ExecutorService's execute
提问by Cheok Yan Cheng
How should I choose between ExecutorService'ssubmitor execute, if the returned value is not my concern?
如果返回的值不是我所关心的,我应该如何在ExecutorService 的submit或execute之间进行选择?
If I test both, I didn't see any differences among the two except the returned value.
如果我同时测试两者,除了返回值之外,我没有发现两者之间有任何差异。
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.execute(new Task());
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.submit(new Task());
采纳答案by hochraldo
There is a difference concerning exception/error handling.
在异常/错误处理方面存在差异。
A task queued with execute()
that generates some Throwable
will cause the UncaughtExceptionHandler
for the Thread
running the task to be invoked. The default UncaughtExceptionHandler
, which typically prints the Throwable
stack trace to System.err
, will be invoked if no custom handler has been installed.
与排队的任务execute()
是产生一些Throwable
将导致UncaughtExceptionHandler
对Thread
正在运行的任务被调用。如果未安装自定义处理程序,则将调用默认值UncaughtExceptionHandler
(通常将Throwable
堆栈跟踪打印到 )System.err
。
On the other hand, a Throwable
generated by a task queued with submit()
will bind the Throwable
to the Future
that was produced from the call to submit()
. Calling get()
on that Future
will throw an ExecutionException
with the original Throwable
as its cause (accessible by calling getCause()
on the ExecutionException
).
另一方面,Throwable
由排队的任务生成的 asubmit()
将绑定Throwable
到Future
调用产生的submit()
。调用get()
上Future
会抛出一个ExecutionException
与原来的Throwable
(通过调用访问作为其事业getCause()
上的ExecutionException
)。
回答by Syntax
Taken from the Javadoc:
摘自Javadoc:
Method
submit
extends base method {@link Executor#execute
} by creating and returning a {@link Future} that can be used to cancel execution and/or wait for completion.
方法通过创建和返回可用于取消执行和/或等待完成的 {@link Future} 来
submit
扩展基本方法 {@link Executor#execute
}。
Personally I prefer the use of execute because it feels more declarative, although this really is a matter of personal preference.
我个人更喜欢使用 execute ,因为它感觉更具声明性,尽管这确实是个人喜好的问题。
To give more information: in the case of the ExecutorService
implementation, the core implementation being returned by the call to Executors.newSingleThreadedExecutor()
is a ThreadPoolExecutor
.
提供更多信息:在实现的情况下,ExecutorService
调用返回的核心实现Executors.newSingleThreadedExecutor()
是 a ThreadPoolExecutor
。
The submit
calls are provided by its parent AbstractExecutorService
and all call execute internally. execute is overridden/provided by the ThreadPoolExecutor
directly.
该submit
呼叫通过其母公司提供的AbstractExecutorService
所有内部调用执行。execute 被ThreadPoolExecutor
直接覆盖/提供。
回答by Steven
if you dont care about the return type, use execute. it's the same as submit, just without the return of Future.
如果您不关心返回类型,请使用执行。和 submit 一样,只是没有 Future 的返回。
回答by rxg
From the Javadoc:
从Javadoc:
The command may execute in a new thread, in a pooled thread, or in the calling thread, at the discretion of the Executor implementation.
根据 Executor 实现的判断,该命令可以在新线程、池线程或调用线程中执行。
So depending on the implementation of Executor
you may find that the submitting thread blocks while the task is executing.
因此,根据Executor
您的实现,您可能会发现提交线程在任务执行时阻塞。
回答by Ravindra babu
execute: Use it for fire and forget calls
执行:将其用于火灾和忘记电话
submit: Use it to inspect the result of method call and take appropriate action on Future
objected returned by the call
submit:使用它来检查方法调用的结果并对调用Future
返回的对象采取适当的行动
From javadocs
来自javadocs
submit(Callable<T> task)
submit(Callable<T> task)
Submits a value-returning task for execution and returns a Future representing the pending results of the task.
提交一个返回值的任务以供执行,并返回一个表示任务未决结果的 Future。
Future<?> submit(Runnable task)
Future<?> submit(Runnable task)
Submits a Runnable task for execution and returns a Future representing that task.
提交一个 Runnable 任务以供执行,并返回一个代表该任务的 Future。
void execute(Runnable command)
Executes the given command at some time in the future. The command may execute in a new thread, in a pooled thread, or in the calling thread, at the discretion of the Executor implementation.
在将来的某个时间执行给定的命令。根据 Executor 实现的判断,该命令可以在新线程、池线程或调用线程中执行。
You have to take precaution while using submit()
. It hides exception in the framework itself unless you embed your task code in try{} catch{}
block.
使用时一定要注意防范submit()
。除非您将任务代码嵌入到try{} catch{}
块中,否则它会在框架本身中隐藏异常。
Example code:This code swallows Arithmetic exception : / by zero
.
示例代码:此代码吞下Arithmetic exception : / by zero
.
import java.util.concurrent.*;
import java.util.*;
public class ExecuteSubmitDemo{
public ExecuteSubmitDemo()
{
System.out.println("creating service");
ExecutorService service = Executors.newFixedThreadPool(10);
//ExtendedExecutor service = new ExtendedExecutor();
service.submit(new Runnable(){
public void run(){
int a=4, b = 0;
System.out.println("a and b="+a+":"+b);
System.out.println("a/b:"+(a/b));
System.out.println("Thread Name in Runnable after divide by zero:"+Thread.currentThread().getName());
}
});
service.shutdown();
}
public static void main(String args[]){
ExecuteSubmitDemo demo = new ExecuteSubmitDemo();
}
}
output:
输出:
java ExecuteSubmitDemo
creating service
a and b=4:0
Same code throws by replacing submit()
with execute
() :
通过替换submit()
为execute
()会抛出相同的代码:
Replace
代替
service.submit(new Runnable(){
with
和
service.execute(new Runnable(){
output:
输出:
java ExecuteSubmitDemo
creating service
a and b=4:0
Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
at ExecuteSubmitDemo.run(ExecuteSubmitDemo.java:14)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
How to handle the these type of scenarios while using submit()?
在使用 submit() 时如何处理这些类型的场景?
- Embed your Task code ( Either Runnable or Callable implementation) with try{} catch{} block code
- Implement
CustomThreadPoolExecutor
- 使用 try{} catch{} 块代码嵌入您的任务代码(Runnable 或 Callable 实现)
- 实施
CustomThreadPoolExecutor
New solution:
新解决方案:
import java.util.concurrent.*;
import java.util.*;
public class ExecuteSubmitDemo{
public ExecuteSubmitDemo()
{
System.out.println("creating service");
//ExecutorService service = Executors.newFixedThreadPool(10);
ExtendedExecutor service = new ExtendedExecutor();
service.submit(new Runnable(){
public void run(){
int a=4, b = 0;
System.out.println("a and b="+a+":"+b);
System.out.println("a/b:"+(a/b));
System.out.println("Thread Name in Runnable after divide by zero:"+Thread.currentThread().getName());
}
});
service.shutdown();
}
public static void main(String args[]){
ExecuteSubmitDemo demo = new ExecuteSubmitDemo();
}
}
class ExtendedExecutor extends ThreadPoolExecutor {
public ExtendedExecutor() {
super(1,1,60,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(100));
}
// ...
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
try {
Object result = ((Future<?>) r).get();
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
if (t != null)
System.out.println(t);
}
}
output:
输出:
java ExecuteSubmitDemo
creating service
a and b=4:0
java.lang.ArithmeticException: / by zero
回答by alfasin
The full answer is a composition of two answers that were published here (plus a bit "extra"):
完整的答案是在这里发布的两个答案的组合(加上一点“额外”):
- By submitting a task (vs. executing it) you get back a future which can be used to get the result or cancel the action. You don't have this kind of control when you
execute
(because its return type idvoid
) execute
expects aRunnable
whilesubmit
can take either aRunnable
or aCallable
as an argument (for more info about the difference between the two - see below).execute
bubbles up any unchecked-exceptions right away (it cannot throw checked exceptions!!!), whilesubmit
binds anykind of exception to the future that returns as a result, and only when you callfuture.get()
a the (wrapped) exception will be thrown . The Throwable that you'll get is an instance ofExecutionException
and if you'll call this object'sgetCause()
it will return the original Throwable.
- 通过提交任务(与执行任务相比),您将获得一个可用于获取结果或取消操作的未来。你没有这种控制
execute
(因为它的返回类型 idvoid
) execute
期望一段Runnable
时间submit
可以将 aRunnable
或 aCallable
作为参数(有关两者之间差异的更多信息 - 请参见下文)。execute
立即冒泡任何未经检查的异常(它不能抛出已检查的异常!!!),同时submit
将任何类型的异常绑定到作为结果返回的未来,并且只有当您调用future.get()
(包装的)异常时才会抛出。您将获得的 Throwable 是一个实例,ExecutionException
如果您调用此对象getCause()
,它将返回原始 Throwable。
A few more (related) points:
还有一些(相关)点:
- Even if the task that you want to
submit
does not require returning a result, you can still useCallable<Void>
(instead of using aRunnable
). - Cancellation of tasks can be done using the interruptmechanism. Here's an exampleof how to implement a cancellation policy
To sum up, it's a better practice to use submit
with a Callable
(vs. execute
with a Runnable
). And I'll quote from "Java concurrency in practice" By Brian Goetz:
总而言之,submit
与 a Callable
(vs. execute
with a Runnable
)一起使用是更好的做法。我将引用 Brian Goetz 的“实践中的 Java 并发”:
6.3.2 Result-bearing tasks: Callable and Future
The Executor framework uses Runnable as its basic task representation. Runnable is a fairly limiting abstraction; run cannot return a value or throw checked exceptions, although it can have side effects such as writing to a log file or placing a result in a shared data structure. Many tasks are effectively deferred computations—executing a database query, fetching a resource over the network, or computing a complicated function. For these types of tasks, Callable is a better abstraction: it expects that the main entry point, call, will return a value and anticipates that it might throw an exception.7 Executors includes several utility methods for wrapping other types of tasks, including Runnable and java.security.PrivilegedAction, with a Callable.
6.3.2 结果承载任务:Callable 和 Future
Executor 框架使用 Runnable 作为其基本任务表示。Runnable 是一个相当有限的抽象;run 不能返回值或抛出已检查的异常,尽管它可能会产生副作用,例如写入日志文件或将结果放入共享数据结构中。许多任务都是有效的延迟计算——执行数据库查询、通过网络获取资源或计算复杂的函数。对于这些类型的任务,Callable 是一个更好的抽象:它期望主入口点 call 将返回一个值并预计它可能会抛出异常。 7 Executors 包括几个用于包装其他类型任务的实用方法,包括 Runnable和 java.security.PrivilegedAction,带有一个 Callable。
回答by abhihello123
Just adding to the accepted answer-
只是添加到接受的答案 -
However, exceptions thrown from tasks make it to the uncaught exception handler only for tasks submitted with execute(); for tasks submitted with submit() to the executor service, any thrown exception is considered to be part of the task's return status.
但是,从任务抛出的异常只针对使用 execute() 提交的任务进入未捕获的异常处理程序;对于使用 submit() 提交给执行器服务的任务,任何抛出的异常都被视为任务返回状态的一部分。