ExecutorService的execute和submit方法

由于以前一直是用的execute方法,最近有个状况须要用到submit方法,因此研究了下。 java


三个区别: 并发

一、接收的参数不同 app

二、submit有返回值,而execute没有 dom

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.  ide

用到返回值的例子,好比说我有不少个作validation的task,我但愿全部的task执行完,而后每一个task告诉我它的执行结果,是成功仍是失败,若是是失败,缘由是什么。而后我就能够把全部失败的缘由综合起来发给调用者。 学习

我的以为cancel execution这个用处不大,不多有须要去取消执行的。 this

而最大的用处应该是第二点。 spa

三、submit方便Exception处理 .net

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),下面的代码是基于它之上修改的。

[java]  view plain copy
  1. import java.util.ArrayList;  
  2. import java.util.List;  
  3. import java.util.Random;  
  4. import java.util.concurrent.Callable;  
  5. import java.util.concurrent.ExecutionException;  
  6. import java.util.concurrent.ExecutorService;  
  7. import java.util.concurrent.Executors;  
  8. import java.util.concurrent.Future;  
  9.   
  10. public class ExecutorServiceTest {  
  11.     public static void main(String[] args) {  
  12.         ExecutorService executorService = Executors.newCachedThreadPool();  
  13.         List<Future<String>> resultList = new ArrayList<Future<String>>();  
  14.   
  15.         // 建立10个任务并执行  
  16.         for (int i = 0; i < 10; i++) {  
  17.             // 使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中  
  18.             Future<String> future = executorService.submit(new TaskWithResult(i));  
  19.             // 将任务执行结果存储到List中  
  20.             resultList.add(future);  
  21.         }  
  22.         executorService.shutdown();  
  23.   
  24.         // 遍历任务的结果  
  25.         for (Future<String> fs : resultList) {  
  26.             try {  
  27.                 System.out.println(fs.get()); // 打印各个线程(任务)执行的结果  
  28.             } catch (InterruptedException e) {  
  29.                 e.printStackTrace();  
  30.             } catch (ExecutionException e) {  
  31.                 executorService.shutdownNow();  
  32.                 e.printStackTrace();  
  33.                 return;  
  34.             }  
  35.         }  
  36.     }  
  37. }  
  38.   
  39. class TaskWithResult implements Callable<String> {  
  40.     private int id;  
  41.   
  42.     public TaskWithResult(int id) {  
  43.         this.id = id;  
  44.     }  
  45.   
  46.     /** 
  47.      * 任务的具体过程,一旦任务传给ExecutorService的submit方法,则该方法自动在一个线程上执行。 
  48.      *  
  49.      * @return  
  50.      * @throws Exception 
  51.      */  
  52.     public String call() throws Exception {  
  53.         System.out.println("call()方法被自动调用,干活!!!             " + Thread.currentThread().getName());  
  54.         if (new Random().nextBoolean())  
  55.             throw new TaskException("Meet error in task." + Thread.currentThread().getName());  
  56.         // 一个模拟耗时的操做  
  57.         for (int i = 999999999; i > 0; i--)  
  58.             ;  
  59.         return "call()方法被自动调用,任务的结果是:" + id + "    " + Thread.currentThread().getName();  
  60.     }  
  61. }  
  62.   
  63. class TaskException extends Exception {  
  64.     public TaskException(String message) {  
  65.         super(message);  
  66.     }  
  67. }  

执行的结果相似于:

[java]  view plain copy
  1. call()方法被自动调用,干活!!!             pool-1-thread-1  
  2. call()方法被自动调用,干活!!!             pool-1-thread-2  
  3. call()方法被自动调用,干活!!!             pool-1-thread-3  
  4. call()方法被自动调用,干活!!!             pool-1-thread-5  
  5. call()方法被自动调用,干活!!!             pool-1-thread-7  
  6. call()方法被自动调用,干活!!!             pool-1-thread-4  
  7. call()方法被自动调用,干活!!!             pool-1-thread-6  
  8. call()方法被自动调用,干活!!!             pool-1-thread-7  
  9. call()方法被自动调用,干活!!!             pool-1-thread-5  
  10. call()方法被自动调用,干活!!!             pool-1-thread-8  
  11. call()方法被自动调用,任务的结果是:0    pool-1-thread-1  
  12. call()方法被自动调用,任务的结果是:1    pool-1-thread-2  
  13. java.util.concurrent.ExecutionException: com.cicc.pts.TaskException: Meet error in task.pool-1-thread-3  
  14.     at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)  
  15.     at java.util.concurrent.FutureTask.get(FutureTask.java:83)  
  16.     at com.cicc.pts.ExecutorServiceTest.main(ExecutorServiceTest.java:29)  
  17. Caused by: com.cicc.pts.TaskException: Meet error in task.pool-1-thread-3  
  18.     at com.cicc.pts.TaskWithResult.call(ExecutorServiceTest.java:57)  
  19.     at com.cicc.pts.TaskWithResult.call(ExecutorServiceTest.java:1)  
  20.     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)  
  21.     at java.util.concurrent.FutureTask.run(FutureTask.java:138)  
  22.     at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)  
  23.     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)  
  24.     at java.lang.Thread.run(Thread.java:619)  
能够看见一旦某个task出错,其它的task就中止执行。
相关文章
相关标签/搜索