Che*_*eng 187 java multithreading executorservice
如果返回的值不是我关注的话,我应该如何在ExecutorService的 提交或执行之间进行选择?
如果我同时测试两者,除了返回值之外,我没有看到两者之间有任何差异.
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.execute(new Task());
Run Code Online (Sandbox Code Playgroud)
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.submit(new Task());
Run Code Online (Sandbox Code Playgroud)
小智 199
异常/错误处理有所不同.
与排队的任务execute()
是产生一些Throwable
将导致UncaughtExceptionHandler
对Thread
正在运行的任务被调用.如果未安装自定义处理程序,则将调用默认值UncaughtExceptionHandler
(通常将Throwable
堆栈跟踪打印到)System.err
.
另一方面,Throwable
由排队的任务生成的submit()
将绑定Throwable
到Future
从调用生成的任务submit()
.调用get()
上Future
会抛出一个ExecutionException
与原来的Throwable
(通过调用访问作为其事业getCause()
上的ExecutionException
).
Rav*_*abu 59
执行:用于火灾和忘记呼叫
submit:用它来检查方法调用的结果,Future
并对调用返回的对象采取适当的操作
来自javadocs
submit(Callable<T> task)
提交值返回任务以执行并返回表示任务的挂起结果的Future.
Future<?> submit(Runnable task)
提交Runnable任务以执行并返回表示该任务的Future.
void execute(Runnable command)
Run Code Online (Sandbox Code Playgroud)
在将来的某个时间执行给定的命令.该命令可以在Executor实现的判断下在新线程,池化线程或调用线程中执行.
使用时必须采取预防措施submit()
.除非您将任务代码嵌入try{} catch{}
块中,否则它会在框架中隐藏异常.
示例代码:此代码吞下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();
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
java ExecuteSubmitDemo
creating service
a and b=4:0
Run Code Online (Sandbox Code Playgroud)
通过替换submit()
为execute
()抛出相同的代码:
更换
service.submit(new Runnable(){
Run Code Online (Sandbox Code Playgroud)
同
service.execute(new Runnable(){
Run Code Online (Sandbox Code Playgroud)
输出:
java ExecuteSubmitDemo
creating service
a and b=4:0
Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
at ExecuteSubmitDemo$1.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)
Run Code Online (Sandbox Code Playgroud)
如何在使用submit()时处理这些类型的场景?
CustomThreadPoolExecutor
新解决方案:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
java ExecuteSubmitDemo
creating service
a and b=4:0
java.lang.ArithmeticException: / by zero
Run Code Online (Sandbox Code Playgroud)
取自Javadoc:
方法通过创建和返回可用于取消执行和/或等待完成的{@link Future}来
submit
扩展基本方法{@link Executor#execute
}.
我个人更喜欢使用执行,因为它感觉更具声明性,尽管这确实是个人偏好的问题.
提供更多信息:在实现的情况下,ExecutorService
调用返回的核心实现Executors.newSingleThreadedExecutor()
是a ThreadPoolExecutor
.
该submit
呼叫通过其母公司提供的AbstractExecutorService
所有内部调用执行.执行被ThreadPoolExecutor
直接覆盖/提供.
完整答案由此处发布的两个答案组成(加上一点“额外”):
\n\nexecute
(因为它的返回类型 idvoid
)execute
预计需要一段Runnable
时间submit
,可以采取 aRunnable
或 aCallable
作为参数(有关两者之间差异的更多信息 - 请参阅下文)。execute
立即冒出任何未检查的异常(它不能抛出检查的异常!!!),同时将任何submit
类型的异常绑定到作为结果返回的未来,并且只有当您调用(包装的)异常时才会抛出。您将获得的 Throwable 是一个实例,如果您调用该对象的future.get()
ExecutionException
getCause()
它将返回原始 Throwable。还有一些(相关的)点:
\n\n\n\nsubmit
总而言之,使用a是更好的做法Callable
(相对于execute
使用 a Runnable
)。我将引用 Brian Goetz 的《Java 并发实践》:
\n\n6.3.2 结果承载任务:Callable 和 Future
\n\nExecutor 框架使用 Runnable 作为其基本任务表示。Runnable 是一个相当有限的抽象;run 无法返回值或抛出检查异常,尽管它可能会产生副作用,例如写入日志文件或将结果放入共享数据结构中。许多任务都有效地推迟了计算,例如执行数据库查询、通过网络获取资源或计算复杂的函数。对于这些类型的任务,Callable 是一个更好的抽象:它预计主入口点 call 将返回一个值,并预计它可能抛出异常。7 执行器包含几个实用程序方法,用于使用 Callable 包装其他类型的任务,包括 Runnable 和 java.security.PrivilegedAction。
\n
归档时间: |
|
查看次数: |
89076 次 |
最近记录: |