在 ExecutorService 的提交和 ExecutorService 的执行之间进行选择
我应该如何在 ExecutorService 的 提交 或 执行,如果返回值不是我关心的?
如果我测试两者,除了返回值之外,我没有看到两者之间有任何差异。
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.execute(new Task());
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.submit(new Task());
How should I choose between ExecutorService's submit or execute, if the returned value is not my concern?
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());
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
异常/错误处理方面存在差异。
使用
execute()
排队并生成一些Throwable
的任务将导致运行该任务的Thread
的UncaughtExceptionHandler
被调用。如果尚未安装自定义处理程序,将调用默认的 UncaughtExceptionHandler 通常会将Throwable
堆栈跟踪打印到System.err
。另一方面,由使用
submit()
排队的任务生成的Throwable
会将Throwable
绑定到Future
> 这是通过调用submit()
生成的。在该Future
上调用get()
将抛出一个ExecutionException
,其原因是原始的Throwable
(可通过调用ExecutionException
上的getCause()
)。There is a difference concerning exception/error handling.
A task queued with
execute()
that generates someThrowable
will cause theUncaughtExceptionHandler
for theThread
running the task to be invoked. The defaultUncaughtExceptionHandler
, which typically prints theThrowable
stack trace toSystem.err
, will be invoked if no custom handler has been installed.On the other hand, a
Throwable
generated by a task queued withsubmit()
will bind theThrowable
to theFuture
that was produced from the call tosubmit()
. Callingget()
on thatFuture
will throw anExecutionException
with the originalThrowable
as its cause (accessible by callinggetCause()
on theExecutionException
).执行:使用它进行即发即忘调用,
来自 ExecutorService 作者:docs.oracle.com
提交:
submit(Callabletask)
未来提交(可运行任务)
使用
submit()
时必须采取预防措施。除非您将任务代码嵌入到try{} catch{}
块中,否则它会将异常隐藏在框架本身中。示例代码:此代码吞掉
算术异常:/ 为零
。输出:
将
submit()
替换为execute
() 会抛出相同的代码:替换
为
输出:
如何在使用提交时处理这些类型的场景()?
CustomThreadPoolExecutor
,如中所述ThreadPoolExecutor 作者:docs .oracle.com 具有ExtendedExecutor
类处理afterExecute
方法新解决方案:
输出:
execute: Use it for fire and forget calls
From ExecutorService by docs.oracle.com
submit:
submit(Callable<T> task)
Future<?> submit(Runnable task)
You have to take precaution while using
submit()
. It hides exception in the framework itself unless you embed your task code intry{} catch{}
block.Example code: This code swallows
Arithmetic exception : / by zero
.output:
Same code throws by replacing
submit()
withexecute
() :Replace
with
output:
How to handle the these type of scenarios while using submit()?
CustomThreadPoolExecutor
as explained in ThreadPoolExecutor by docs.oracle.com withExtendedExecutor
class handlingafterExecute
methodNew solution:
output:
如果您不关心返回类型,请使用execute。和submit一样,只是没有Future的返回。
if you dont care about the return type, use execute. it's the same as submit, just without the return of Future.
摘自 Javadoc:
就我个人而言,我更喜欢使用执行,因为它感觉更具声明性,尽管这确实是个人喜好的问题。
提供更多信息:在
ExecutorService
实现的情况下,调用Executors.newSingleThreadedExecutor()
返回的核心实现是ThreadPoolExecutor
>。submit
调用由其父AbstractExecutorService
提供,并且所有调用都在内部执行。 execute 由 ThreadPoolExecutor 直接覆盖/提供。Taken from the Javadoc:
Personally I prefer the use of execute because it feels more declarative, although this really is a matter of personal preference.
To give more information: in the case of the
ExecutorService
implementation, the core implementation being returned by the call toExecutors.newSingleThreadedExecutor()
is aThreadPoolExecutor
.The
submit
calls are provided by its parentAbstractExecutorService
and all call execute internally. execute is overridden/provided by theThreadPoolExecutor
directly.完整的答案是此处发布的两个答案的组合(加上一点“额外”):
execute
时,您没有这种控制权(因为它的返回类型idvoid
)execute
需要一个Runnable
code> 而submit
可以采用Runnable
或Callable
作为参数(有关两者之间差异的更多信息 - 请参阅下文) 。execute
立即冒出任何未检查的异常(它不能抛出已检查的异常!!!),而submit
将任何类型的异常绑定到future 作为结果返回,并且只有当您调用 future.get() 时才会抛出(包装的)异常。您将获得的 Throwable 是 ExecutionException 的一个实例,如果您调用该对象的 getCause() ,它将返回原始的 Throwable。还有一些(相关)点:
提交
的任务不需要返回结果,您仍然可以使用
Callable
(而不是使用Runnable
)。总而言之,使用
submit是更好的做法code> 与
Callable
(与execute
与Runnable
)。我将引用 Brian Goetz 的《Java 并发实践》:The full answer is a composition of two answers that were published here (plus a bit "extra"):
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 any kind 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.A few more (related) points:
submit
does not require returning aresult, you can still use
Callable<Void>
(instead of using aRunnable
).To sum up, it's a better practice to use
submit
with aCallable
(vs.execute
with aRunnable
). And I'll quote from "Java concurrency in practice" By Brian Goetz:execute
可能会也可能不会使用来自 Javadoc:
因此,根据 Executor 的实现,您可能会发现提交线程在任务执行时会阻塞。
为了确保您的任务在另一个线程上运行,请勿调用
执行
。相反,请调用提交
,invokeAll
,或invokeAny
。execute
may, or may not, use another threadFrom the Javadoc:
So depending on the implementation of
Executor
you may find that the submitting thread blocks while the task is executing.To be sure your task runs on another thread, do not call
execute
. Instead, callsubmit
,invokeAll
, orinvokeAny
.只是添加到已接受的答案中 -
来源
Just adding to the accepted answer-
Source