ExecutorService中submit和execute的区别(转)
在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动、调度、管理线程的一大堆API了。在Java5以后,通过Executor来启动线程比用Thread的start()更好。在新特征中,可以很容易控制线程的启动、执行和关闭过程,还可以很容易使用线程池的特性。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by IntelliJ IDEA.
*
* @author leizhimin 2008-11-25 14:28:59
*/
publicclass TestCachedThreadPool {
publicstaticvoid main(String[] args) {
// ExecutorService executorService = Executors.newCachedThreadPool();
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
executorService.execute(new TestRunnable());
System.out.println("************* a" + i + " *************");
}
executorService.shutdown();
}
}
class TestRunnable implements Runnable {
publicvoid run() {
System.out.println(Thread.currentThread().getName() + "线程被调用了。");
while (true) {
try {
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
************* a1 *************
pool-1-thread-2线程被调用了。
************* a2 *************
pool-1-thread-3线程被调用了。
pool-1-thread-1线程被调用了。
************* a3 *************
************* a4 *************
pool-1-thread-4线程被调用了。
pool-1-thread-5线程被调用了。
pool-1-thread-2
pool-1-thread-1
pool-1-thread-3
pool-1-thread-5
pool-1-thread-4
pool-1-thread-2
pool-1-thread-1
pool-1-thread-3
pool-1-thread-5
pool-1-thread-4
......
import java.util.List;
import java.util.concurrent.*;
/**
* Callable接口测试
*
* @author leizhimin 2008-11-26 9:20:13
*/
publicclass CallableDemo {
publicstaticvoid main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<String>> resultList = new ArrayList<Future<String>>();
//创建10个任务并执行
for (int i = 0; i < 10; i++) {
//使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
Future<String> future = executorService.submit(new TaskWithResult(i));
//将任务执行结果存储到List中
resultList.add(future);
}
//遍历任务的结果
for (Future<String> fs : resultList) {
try {
System.out.println(fs.get()); //打印各个线程(任务)执行的结果
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
//启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用。
executorService.shutdown();
}
}
}
}
class TaskWithResult implements Callable<String> {
privateint id;
public TaskWithResult(int id) {
this.id = id;
}
/**
* 任务的具体过程,一旦任务传给ExecutorService的submit方法,则该方法自动在一个线程上执行。
*
* @return
* @throws Exception
*/
public String call() throws Exception {
System.out.println("call()方法被自动调用,干活!!! " + Thread.currentThread().getName());
//一个模拟耗时的操作
for (int i = 999999; i > 0; i--) ;
return"call()方法被自动调用,任务的结果是:" + id + " " + Thread.currentThread().getName();
}
}
call()方法被自动调用,干活!!! pool-1-thread-3
call()方法被自动调用,干活!!! pool-1-thread-4
call()方法被自动调用,干活!!! pool-1-thread-6
call()方法被自动调用,干活!!! pool-1-thread-2
call()方法被自动调用,干活!!! pool-1-thread-5
call()方法被自动调用,任务的结果是:0 pool-1-thread-1
call()方法被自动调用,任务的结果是:1 pool-1-thread-2
call()方法被自动调用,干活!!! pool-1-thread-2
call()方法被自动调用,干活!!! pool-1-thread-6
call()方法被自动调用,干活!!! pool-1-thread-4
call()方法被自动调用,任务的结果是:2 pool-1-thread-3
call()方法被自动调用,干活!!! pool-1-thread-3
call()方法被自动调用,任务的结果是:3 pool-1-thread-4
call()方法被自动调用,任务的结果是:4 pool-1-thread-5
call()方法被自动调用,任务的结果是:5 pool-1-thread-6
call()方法被自动调用,任务的结果是:6 pool-1-thread-2
call()方法被自动调用,任务的结果是:7 pool-1-thread-6
call()方法被自动调用,任务的结果是:8 pool-1-thread-4
call()方法被自动调用,任务的结果是:9 pool-1-thread-3
Process finished with exit code 0
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
因为之前一直是用的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),下面的代码是基于它之上修改的。
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Random;
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Future;
- public class ExecutorServiceTest {
- public static void main(String[] args) {
- ExecutorService executorService = Executors.newCachedThreadPool();
- List<Future<String>> resultList = new ArrayList<Future<String>>();
- // 创建10个任务并执行
- for (int i = 0; i < 10; i++) {
- // 使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
- Future<String> future = executorService.submit(new TaskWithResult(i));
- // 将任务执行结果存储到List中
- resultList.add(future);
- }
- executorService.shutdown();
- // 遍历任务的结果
- for (Future<String> fs : resultList) {
- try {
- System.out.println(fs.get()); // 打印各个线程(任务)执行的结果
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- executorService.shutdownNow();
- e.printStackTrace();
- return;
- }
- }
- }
- }
- class TaskWithResult implements Callable<String> {
- private int id;
- public TaskWithResult(int id) {
- this.id = id;
- }
- /**
- * 任务的具体过程,一旦任务传给ExecutorService的submit方法,则该方法自动在一个线程上执行。
- *
- * @return
- * @throws Exception
- */
- public String call() throws Exception {
- System.out.println("call()方法被自动调用,干活!!! " + Thread.currentThread().getName());
- if (new Random().nextBoolean())
- throw new TaskException("Meet error in task." + Thread.currentThread().getName());
- // 一个模拟耗时的操作
- for (int i = 999999999; i > 0; i--)
- ;
- return "call()方法被自动调用,任务的结果是:" + id + " " + Thread.currentThread().getName();
- }
- }
- class TaskException extends Exception {
- public TaskException(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()方法被自动调用,任务的结果是:0 pool-1-thread-1
- call()方法被自动调用,任务的结果是:1 pool-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就停止执行。
ExecutorService中submit和execute的区别(转)的更多相关文章
- ExecutorService中submit()和execute()的区别
在使用java.util.concurrent下关于线程池一些类的时候,相信很多人和我一样,总是分不清submit()和execute()的区别,今天从源码方面分析总结一下. 通常,我们通过Execu ...
- ExecutorService中submit和execute的区别
在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动.调度.管理线程的一大堆API了.在Java5以后,通过Executor来启动线程比用Thread的start()更好.在新特征中 ...
- ExecutorService中submit和execute的区别<转>
在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动.调度.管理线程的一大堆API了.在Java5以后,通过Executor来启动线程比用Thread的start()更好.在新特征中 ...
- 多线程ExecutorService中submit和execute区别
submit和execute都是 ExecutorService 的方法,都是添加线程到线程池中. 区别 三个区别: 1.接收的参数不一样 2.submit有返回值,而execute没有 Method ...
- 线程池中 submit()和 execute()方法有什么区别?(未完成)
线程池中 submit()和 execute()方法有什么区别?(未完成)
- 【多线程 5】线程池的类型以及submit()和execute()的区别
就跟题目说的一样,本篇博客,本宝宝主要介绍两个方面的内容,其一:线程池的类型及其应用场景:其二:submit和execute的区别.那么需要再次重申的是,对于概念性的东西,我一般都是从网上挑选截取,再 ...
- 线程池的类型以及执行线程submit()和execute()的区别
就跟题目说的一样,本篇博客,本宝宝主要介绍两个方面的内容,其一:线程池的类型及其应用场景:其二:submit和execute的区别.那么需要再次重申的是,对于概念性的东西,我一般都是从网上挑选截取,再 ...
- html中submit和button的区别(总结) [ 转自欣步同学 ]
html中submit和button的区别(总结) submit是button的一个特例,也是button的一种,它把提交这个动作自动集成了. 如果表单在点击提交按钮后需要用JS进行处理(包括输入验证 ...
- 线程池提交任务时submit()和execute()的区别
因为之前一直是用的execute方法,最近有个情况需要用到submit方法,所以研究了下. 他们的区别: 1.execut()可以添加一个Runable任务,submit()不仅可以添加Runable ...
随机推荐
- 扫盲贴000---关于python中的if __name__ == '__main__'
对于python中的__name__变量,根据调用python文件的方式不同,__name__变量的值也会不同.假如我有一个名为hello_world.py的python脚本,当我的目的是直接运行这个 ...
- quartz_job
quartz--job job是执行任务所需的Java类. 在quartz中job分为两种,有状态和无状态的.job是无状态的,statefuljob是有状态的. 通过实现job或者statefulj ...
- Android 4.0 源代码结构
Android源码的第一级目录结构 Android/abi (abi相关代码.ABI:application binary interface,应用程序二进制接口) Android/bioni ...
- C语言学习笔记(一)_hello world程序中涉及的c语言元素
#include <stdio.h> //使用printf函数之前必须include<stdio.h> int main() { int i; //声明一个变量 printf( ...
- 通过pinyin4j.jar将(汉字拼音混合字符串)转化成字母首字母
通过pinyin4j.jar将(汉字拼音混合字符串)转化成字母首字母 例如 我的中国心 ==> wdzgx 我的中国心ya ==> wdzgxya woai我的中国 ==> w ...
- .Net Mail SMTP 发送网络邮件
刚刚迈入"开发"的行列 一直有一个想法 我什么时候能给我庞大的用户信息数据库给每一位用户邮箱发送推荐信息呢? 刚迈入"编程两个月的时间" 我采用 SMTP 发送 ...
- shift
-------siwuxie095 shift 更改批处理文件中可替换参数的位置 语法: SHIFT [/n] 如果命令扩展被启用,SHIFT 命令支持 /n 命令行开关:该命令行开关告诉 命令从第 ...
- JavaScript取得Format后的当前时间
function getNowFormatDate() { var date = new Date(); var seperator1 = "-"; var seperator2 ...
- JS产生随机数
<script> function GetRandomNum(Min,Max){ var Range = Max - Min; var Rand = Math.random() ...
- 一个简单算法题引发的思考<DNA sorting>(about cin/template/new etc)
首先是昨天在北京大学oj网上看到一个简单的算法题目,虽然简单,但是如何完成一段高效.简洁.让人容易看懂的代码对于我这个基础不好,刚刚进入计算机行业的小白来说还是有意义的.而且在写代码的过程中,会发现自 ...