如果返回值不是我关心的,我应该如何选择ExecutorService的submit还是execute?
如果我同时测试这两种方法,除了返回值之外,我看不到两者之间的任何区别。
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.execute(new Task());
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.submit(new Task());
7条答案
按热度按时间u1ehiz5o1#
在异常/错误处理方面存在差异。
与
execute()
一起排队的任务生成一些Throwable
,将导致运行该任务的Thread
的UncaughtExceptionHandler
被调用。默认的UncaughtExceptionHandler
通常会将Throwable
堆栈跟踪打印到System.err
,如果没有安装自定义处理程序,则将调用该默认的UncaughtExceptionHandler
。另一方面,与
submit()
一起排队的任务生成的Throwable
将把Throwable
绑定到调用submit()
生成的Future
。在Future
上调用get()
将抛出一个ExecutionException
,其原因是原始Throwable
(通过在ExecutionException
上调用getCause()
来访问)。f8rj6qna2#
执行:用它来生火和忘记电话
来自ExecutorService,作者docs.oracle.com
提交:
方法submit通过创建和返回一个Future来扩展基本方法Executor.execute(Runnable),Future可用于取消执行和/或等待完成
submit(Callable<T> task)
提交一个返回值的任务以供执行,并返回一个Future,表示任务的挂起结果。
Future<?> submit(Runnable task)
提交Runnable任务以供执行,并返回表示该任务的Future。
在将来的某个时间执行给定的命令。该命令可以在新线程、池线程或调用线程中执行,具体由Executor实现决定。
在使用
submit()
时必须采取预防措施。它隐藏了框架本身的异常,除非你将你的任务代码嵌入到try{} catch{}
块中。**示例代码:**此代码吞下
Arithmetic exception : / by zero
。输出:
将
submit()
替换为execute
()抛出相同的代码:替换
与
输出:
如何在使用submit()时处理这些类型的场景?
1.使用try{} catch{}块代码嵌入任务代码(* Runnable或Callable实现)*
1.使用
ExtendedExecutor
类处理afterExecute
方法,按照docs.oracle.com的ThreadPoolExecutor中的说明实现CustomThreadPoolExecutor
新方案:
输出:
7eumitmz3#
如果你不关心返回类型,使用execute。它和submit一样,只是没有返回Future。
0h4hbjxa4#
在Javadoc中:
方法
submit
通过创建和返回一个{@link Future}来扩展基方法{@link Executor#execute
},该{@link Future}可用于取消执行和/或等待完成。就我个人而言,我更喜欢使用execute,因为它感觉更具有声明性,尽管这实际上是个人偏好的问题。
给予更多信息:在
ExecutorService
实现的情况下,调用Executors.newSingleThreadedExecutor()
返回的核心实现是ThreadPoolExecutor
。submit
调用由其父AbstractExecutorService
提供,所有调用都在内部执行。execute由ThreadPoolExecutor
直接覆盖/提供。bvjveswy5#
完整的答案是这里发表的两个答案的合成(加上一点“额外的”):
execute
时,你没有这种控制(因为它的返回类型id为void
)execute
需要Runnable
,而submit
可以接受Runnable
或Callable
作为参数(有关两者之间差异的更多信息-请参阅下文)。execute
会立即弹出任何未检查的异常(它不能抛出检查的异常!)!!),而submit
将 any 类型的异常绑定到作为结果返回的future,并且只有当您调用future.get()
时,才会抛出( Package 的)异常。你将得到的Throwable是ExecutionException
的一个示例,如果你调用这个对象的getCause()
,它将返回原始的Throwable。更多(相关):
submit
的任务不需要返回结果,你仍然可以使用Callable<Void>
(而不是使用Runnable
)。总而言之,将
submit
与Callable
一起使用是一种更好的做法(而不是将submit
与Callable
一起使用)。execute
与Runnable
)。我将引用Brian Goetz的“Java并发性实践”:6.3.2结果任务:可赎回和未来
Executor框架使用Runnable作为其基本任务表示。Runnable是一个相当有限的抽象;run不能返回值或抛出检查异常,尽管它可能会产生副作用,例如写入日志文件或将结果放入共享数据结构中。许多任务实际上都是延迟计算执行数据库查询、通过网络获取资源或计算复杂函数。对于这些类型的任务,Callable是一个更好的抽象:它预期主入口点call将返回一个值,并预期它可能抛出一个异常。7 Executors包括几个实用程序方法,用于 Package 其他类型的任务,包括Runnable和java.security.PrivilegedAction,以及Callable。
e4yzc0pl6#
在Javadoc中:
该命令可以在新线程、池线程或调用线程中执行,具体由Executor实现决定。
因此,根据
Executor
的实现,您可能会发现提交线程在任务执行时阻塞。2w3rbyxf7#
只是补充一下公认的答案-
但是,从任务中抛出的异常只有在用execute()提交的任务中才会进入未捕获异常处理程序;对于使用submit()提交给executor服务的任务,任何抛出的异常都被认为是任务返回状态的一部分。
Source