execute方法和submit方法的三個區別:
1、接收的參數不一樣
2、submit有返回值,而execute沒有
Method submit extends base method Executor.execute by creating and returning a Future that can be used to cancel execution and/or wait for completion.
用到返回值的例子,比如說我有很多個做validation的task,我希望所有的task執行完,然後每個task告訴我它的執行結果,是成功還是失敗,如果是失敗,原因是什麼。然後我就可以把所有失敗的原因綜合起來發給調用者。
個人覺得cancel execution這個用處不大,很少有需要去取消執行的。
而最大的用處應該是第二點。
3、submit方便Exception處理
There is a difference when looking at exception handling. If your tasks throws
an exception and if it was submitted with execute this exception will go to the uncaught exception handler (when you don't have provided one explicitly, the default
one will just print the stack trace to System.err). If you submitted the task with submit any thrown
exception, checked or not, is then part of the task's return status. For a task that was submitted with submit and that terminates with an exception, the Future.get will
rethrow this exception, wrapped in an ExecutionException.
意思就是如果你在你的task里會拋出checked或者unchecked exception,而你又希望外面的調用者能夠感知這些exception並做出及時的處理,那麼就需要用到submit,通過捕獲Future.get拋出的異常。
比如說,我有很多更新各種數據的task,我希望如果其中一個task失敗,其它的task就不需要執行了。那我就需要catch Future.get拋出的異常,然後終止其它task的執行,代碼如下:
51cto上有一篇非常好的文章“Java5並發學習”(http://lavasoft.blog.51cto.com/62575/115112),下面的代碼是基於它之上修改的。
importjava.util.ArrayList;
importjava.util.List;
importjava.util.Random;
importjava.util.concurrent.Callable;
importjava.util.concurrent.ExecutionException;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
importjava.util.concurrent.Future;
publicclassExecutorServiceTest {
publicstaticvoidmain(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
List> resultList = newArrayList>();
// 創建10個任務並執行
for(inti =0; i <10; i++) {
// 使用ExecutorService執行Callable類型的任務,並將結果保存在future變量中
Future future = executorService.submit(newTaskWithResult(i));
// 將任務執行結果存儲到List中
resultList.add(future);
}
executorService.shutdown();
// 遍歷任務的結果
for(Future fs : resultList) {
try{
System.out.println(fs.get()); // 打印各個線程(任務)執行的結果
} catch(InterruptedException e) {
e.printStackTrace();
} catch(ExecutionException e) {
executorService.shutdownNow();
e.printStackTrace();
return;
}
}
}
}
classTaskWithResultimplementsCallable {
privateintid;
publicTaskWithResult(intid) {
this.id = id;
}
/**
* 任務的具體過程,一旦任務傳給ExecutorService的submit方法,則該方法自動在一個線程上執行。
*
* @return
* @throws Exception
*/
publicString call()throwsException {
System.out.println("call()方法被自動調用,幹活!!! "+ Thread.currentThread().getName());
if(newRandom().nextBoolean())
thrownewTaskException("Meet error in task."+ Thread.currentThread().getName());
// 一個模擬耗時的操作
for(inti =999999999; i >0; i--)
;
return"call()方法被自動調用,任務的結果是:"+ id +" "+ Thread.currentThread().getName();
}
}
classTaskExceptionextendsException {
publicTaskException(String message) {
super(message);
}
}
執行的結果類似於:
call()方法被自動調用,幹活!!! pool-1-thread-1
call()方法被自動調用,幹活!!! pool-1-thread-2
call()方法被自動調用,幹活!!! pool-1-thread-3
call()方法被自動調用,幹活!!! pool-1-thread-5
call()方法被自動調用,幹活!!! pool-1-thread-7
call()方法被自動調用,幹活!!! pool-1-thread-4
call()方法被自動調用,幹活!!! pool-1-thread-6
call()方法被自動調用,幹活!!! pool-1-thread-7
call()方法被自動調用,幹活!!! pool-1-thread-5
call()方法被自動調用,幹活!!! pool-1-thread-8
call()方法被自動調用,任務的結果是:0pool-1-thread-1
call()方法被自動調用,任務的結果是:1pool-1-thread-2
java.util.concurrent.ExecutionException: com.cicc.pts.TaskException: Meet error in task.pool-1-thread-3
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
at java.util.concurrent.FutureTask.get(FutureTask.java:83)
at com.cicc.pts.ExecutorServiceTest.main(ExecutorServiceTest.java:29)
Caused by: com.cicc.pts.TaskException: Meet error in task.pool-1-thread-3
at com.cicc.pts.TaskWithResult.call(ExecutorServiceTest.java:57)
at com.cicc.pts.TaskWithResult.call(ExecutorServiceTest.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
可以看見一旦某個task出錯,其它的task就停止執行。