ExecutorService引发的血案(二)ExecutorService使用
2015-12-10 18:10
686 查看
上一节中讲到了ExecutorService中有一些管理Thread的方法
通过工厂构建一个ExecutorService实例,然后执行 自定义的
举例:
控制台打印的结果如下:
而且这个方法并不会返回 Future对象,而是返回集合中某个Callable对象的return的值,具体是哪一个呢? 答案是:无法确认(这个跟他的机制有关),但是可以确认的是这个Callable对象是完成了的。
机制:如果 集合中的某个task,完成了(或者抛出异常),那么集合中剩余的task将全部会被取消,不会得到执行。
下面是例子:
这个打印的结果将会是集合中的某一个Callable对象中call()方法返回的值,笔者(不是译者)尝试过多次,打印的结果是不同的, 有时候是
有时候会是
这个方法将会调用 集合中全部的 Callable对象。
返回值:将返回一个包含Future对象的List集合,你可以通过 list中的future对象来获取,callable的返回值。
需要注意的是task结束的时候可能是因为 异常(没有正常结束),所以这个task可能并没有成功。但是通过future对象是无法判断,task 是否成功执行 结束,还是 异常 结束。
举例:如果你的应用通过main()方法启动,并且你的 应用中存在一个 激活的 ExecutorService,那么即使你的
结论:jvm是可能无法关闭
通过调用ExecutorService中的shutdown方法可以终止该ExecutorService中的线程,但是ExecutorService并不会立即关闭,但是ExecutorService已经不会再接收新的task了,等到所有的thread完成各自的task,那么这个ExecutorService就会关闭。并且所有task中的结果 会在shutdown方法执行之前 submit(提交),都是已经执行完成了的。并不会存在没有的执行的task。
结论:手动调用shutdown并不会立即关闭ExecutorService,而是等待ExecutorService中所有的任务完成,并且提交之后,才会关闭的。(所以手动调用shotdown方法,可以不必担心存在剩余任务没有执行的情况)
如果你想立即关闭一个ExecutorService,你可以调用shutdownNow方法来实现。调用这个方法,ExecutorService将会”尝试着“关闭所有正在执行的task,这个关闭的过程会自动跳过那些已经submit的task(节省性能)。但是 对于那些正在 执行的task,并不能保证他们就一定会直接停止执行,或许他们会暂停,或许会执行直到完成,但是ExecutorService会尽力关闭所有正在运行的task。
参考链接:链接1
execute(Runnable) submit(Runnable) submit(Callable) invokeAny(...) invokeAll(...)
execute(Runnable)
这个方法使用的参数是java.lang.Runnable包中的对象,调用这个方法之后将会异步执行
runnable。
ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.execute(new Runnable() { public void run() { System.out.println("Asynchronous task"); } }); executorService.shutdown();
通过工厂构建一个ExecutorService实例,然后执行 自定义的
Runnable,这个方法是没有返回值的,如果你想得到一个返回值,可以使用
Callable对象替代
Runnable(后面会讲到)
submit(Runnable)
这个方法同execute(Runnable)一样,都是异步执行一个task,但是
submit方法是有返回值的,它返回一个
Future对象,通过这个对象,可以检查这个
Runnable实例是否执行完成。
Future future = executorService.submit(new Runnable() { public void run() { System.out.println("Asynchronous task"); } }); future.get(); //returns null if the task has finished correctly. //这个方法返回的是这个任务结束(不一定正常结束)的结果,必要的时候这个方法会等待结果出来。 //如果返回值为null,则表明这个任务已经正常的执行完毕。
submit(Callable)
这个方法的参数和submit(Runnable)不同。 Runnable和Callable的区别是,Runnable中onRun()方法是没有返回值的,而Callable中的call()方法是有返回值的。 call()方法的返回值要如何得到呢? 可以通过 submit(Callable)方法的返回值 Future对象得到。
举例:
Future future = executorService.submit(new Callable(){ public Object call() throws Exception { System.out.println("Asynchronous Callable"); return "Callable Result"; } }); System.out.println("future.get() = " + future.get());
控制台打印的结果如下:
Asynchronous Callable future.get() = Callable Result
invokeAny()
这个方法接收的参数是 Callable(或者Callable的实现类)对象的集合而且这个方法并不会返回 Future对象,而是返回集合中某个Callable对象的return的值,具体是哪一个呢? 答案是:无法确认(这个跟他的机制有关),但是可以确认的是这个Callable对象是完成了的。
机制:如果 集合中的某个task,完成了(或者抛出异常),那么集合中剩余的task将全部会被取消,不会得到执行。
下面是例子:
ExecutorService executorService = Executors.newSingleThreadExecutor(); Set<Callable<String>> callables = new HashSet<Callable<String>>(); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 1"; } }); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 2"; } }); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 3"; } }); String result = executorService.invokeAny(callables); System.out.println("result = " + result); executorService.shutdown();
这个打印的结果将会是集合中的某一个Callable对象中call()方法返回的值,笔者(不是译者)尝试过多次,打印的结果是不同的, 有时候是
Task 1
有时候会是
Task 2等。
invokeAll()
参数:这个方法接收的参数是 Callable(或者Callable的实现类)对象的集合这个方法将会调用 集合中全部的 Callable对象。
返回值:将返回一个包含Future对象的List集合,你可以通过 list中的future对象来获取,callable的返回值。
需要注意的是task结束的时候可能是因为 异常(没有正常结束),所以这个task可能并没有成功。但是通过future对象是无法判断,task 是否成功执行 结束,还是 异常 结束。
ExecutorService executorService = Executors.newSingleThreadExecutor(); Set<Callable<String>> callables = new HashSet<Callable<String>>(); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 1"; } }); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 2"; } }); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 3"; } }); List<Future<String>> futures = executorService.invokeAll(callables); for(Future<String> future : futures){ System.out.println("future.get = " + future.get()); } executorService.shutdown();
ExecutorService Shutdown
当你使用ExecutorService的时候,你应该记得关闭它,这样这些被管理的线程才会停止运行。
举例:如果你的应用通过main()方法启动,并且你的 应用中存在一个 激活的 ExecutorService,那么即使你的
main thread(main线程)已经退出了,这个应用依然会在后台运行。 原因:
ExecutorService中的活跃线程,防止了jvm关闭
ExecutorService。
结论:jvm是可能无法关闭
ExecutorService的,如果某些情况下,你不希望
ExecutorService在后台不受控制的执行,那你在必要的时候 需要手动调用
ExecutorService中的
shutdown方法。
通过调用ExecutorService中的shutdown方法可以终止该ExecutorService中的线程,但是ExecutorService并不会立即关闭,但是ExecutorService已经不会再接收新的task了,等到所有的thread完成各自的task,那么这个ExecutorService就会关闭。并且所有task中的结果 会在shutdown方法执行之前 submit(提交),都是已经执行完成了的。并不会存在没有的执行的task。
结论:手动调用shutdown并不会立即关闭ExecutorService,而是等待ExecutorService中所有的任务完成,并且提交之后,才会关闭的。(所以手动调用shotdown方法,可以不必担心存在剩余任务没有执行的情况)
如果你想立即关闭一个ExecutorService,你可以调用shutdownNow方法来实现。调用这个方法,ExecutorService将会”尝试着“关闭所有正在执行的task,这个关闭的过程会自动跳过那些已经submit的task(节省性能)。但是 对于那些正在 执行的task,并不能保证他们就一定会直接停止执行,或许他们会暂停,或许会执行直到完成,但是ExecutorService会尽力关闭所有正在运行的task。
参考链接:链接1
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树
- [原创]java局域网聊天系统