Java并发包:ExecutorService和ThreadPoolExecutor
文章译自:http://tutorials.jenkov.com/java-util-concurrent/index.html
抽空翻译了一下这个教程的文章,后面会陆续放出,如有不妥,请批评指正。
转自请注明出处。
ExecutorService
Java.util.concurrent.ExecutorService接口代表一种异步执行机制,它能够在后台执行任务。因此ExecutorService与thread pool是非常相似的。事实上,在java.util.package包中ExecutorService的具体实现就是一个线程池的具体实现。
ExcutorService 例子
下面是一个简单的例子
ExecutorService executorService = Executors.newFixedThreadPool(10);executorService.execute(new Runnable() {public void run() {System.out.println("Asynchronous task");}
});executorService.shutdown();
首先,通过newFixedThreadPool()工厂方法创建一个ExecutorService的实例。这个方法创建了一个可以有10个线程执行任务的线程池。
第二,Runnable接口的匿名实现类作为参数被传递给execute()方法。Runable将会被ExecutorService中的一个线程来执行。
任务委托(Task Delegation)
下面的图片说明了一个线程委托一个任务给ExecutorService进行异步执行:
一旦,线程委托任务给ExecutorService,线程会独立任务的执行而继续自己之后的操作。
ExcutorService的使用说明
下面是委托任务给ExecutorService的一些不同的方式:
- execute(Runnable)
- submit(Runnable)
- submit(Callable)
- invokeAny(…)
- invokeAll(…)
下面来逐个看看这些方法。
- execute(Runnable)
execute(Runnable) 方法接受一个java.lang.Runable对象的实例,并异步执行之。下面是一个使用ExecutorService执行Runnable的例子:
ExecutorService executorService = Executors.newSingleThreadExecutor();executorService.execute(new Runnable() {public void run() {System.out.println("Asynchronous task");}
});executorService.shutdown();
这种方式不能获得Runnable执行的结果,如果有这种需要,你将要使用Callable。
- submit(Runnable)
submit(Runnable) 方法也接收一个Runnable接口的具体实现,并返回一个Future对象。Future对象可以用来检测Runable是否执行完成。
Future future = executorService.submit(new Runnable() {public void run() {System.out.println("Asynchronous task");}
});future.get(); //returns null if the task has finished correctly.
- submit(Callable)
submit(Callable)方法与submit(Runnable)方法相似,除了接收的参数有所不同。Callable实例非常类似于Runnable,不同的是call方法可以返回一个结果,Runnable.run()方法不能返回一个结果。
可以通过submit(Callable)方法返回的Future对象获取Callable的结果。下面是一个使用Callable的例子:
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(…)
invokeAny()方法接收一个Callable对象或者Callable的子接口实例的集合作为参数,这个方法不会返回Future,但会返回集合中某一个Callable的结果。你不能确定你得到是哪个Callable的结果。只是已执行完成的Callable中的一个。
如果一个任务已经完成(或者抛出了异常),剩余的Callable任务将被取消。
下面是示例代码:
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集合中一个Callable任务返回的结果。我尝试执行了多次,结果是变化的。有时候是“Task1”,有时候是“Task 2”等。
- invokeAll(…)
invokeAll()接收一个Callable对象的集合作为参数,该方法会调用你传给他的集合中的所有Callable对象。invokeAll()会返回一个Future对象的列表,通过这个列表你可以获取每一个Callable执行的结果。
记住一个任务可能会因为一个异常而结束,因此这时任务并不是真正意义上执行成功了。这在Future上是没有办法来判断的。
下面是示例代码:
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,你的应用程序将仍然会保持运行。ExecutorService中激活的线程会阻止JVM关闭。
为了终止ExecutorService中的线程,你需要调用shutdown()方法。ExecutorService不会立即关闭,但是它也不会接受新的任务,直到它里面的所有线程都执行完毕,ExecutorService才会关闭。所有提交到ExecutorService中的任务会在调用shutdown()方法之前被执行。
如果你想立即关闭ExecutorService,你可以调用shutdownNow()方法。这将会尝试立即停止所有正在执行的任务,并且忽略所有提交的但未被处理的任务。对于正在执行的任务是不能确定的,也许它们停止了,也行它们执行直到结束。
ThreadPoolExecutor
Java.util.concurrent.ThreadPoolExecutor类是ExecutorSerivce接口的具体实现。ThreadPoolExecutor使用线程池中的一个线程来执行给定的任务(Runnable或者Runnable)。
ThreadPoolExecutor内部的线程池包含不定数量的线程。池中线程的数量由下面的这些变量决定:
- corePoolSize
- maximumPoolSize
当一个任务委托给线程池执行,此时如果池线程中线程数少于corePoolSize,即使池中有空闲的线程,线程池中也会创建一个新的线程。
如果任务队列是满的,corePoolSize个线程或者更多的且少于maximumPoolSize的线程正在运行,也会创建一个新的线程来执行任务。
下面图释ThreadPoolExecutor这种原理:
创建ThreadPoolExecutor
ThreadPoolExecutor有多种构造函数。例如:
int corePoolSize = 5;
int maxPoolSize = 10;
long keepAliveTime = 5000;ExecutorService threadPoolExecutor =new ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAliveTime,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
除非你需要显示的给ThreadPoolExecutor指定这些参数,通常使用java.util.concurrent.Executor类中的工厂方法来创建实例。
Java并发包:ExecutorService和ThreadPoolExecutor相关推荐
- Java并发包中的几种ExecutorService
为什么80%的码农都做不了架构师?>>> 1.CachedThreadPool CachedThreadPool首先会按照需要创建足够多的线程来执行任务(Task).随着程序执 ...
- 腾讯面试题Java 并发包之线程池综述
Java 并发包之线程池综述 ■ 线程池的创建 在Java中,您可以通过调整-Xss参数来调节每个线程栈的大小(64bit系统默认1024KB),当减小该值时意味着可以创建更多的线程数,但问题是JVM ...
- java 高并发第三阶段实战_Java 高并发第三阶段实战---Java并发包深入解析与使用详解...
第三阶段的课程主要围绕着Java并发包的使用,展开详细的介绍,主要内容有1.原子包源码剖析,2.并发包工具类详细介绍,3.线程服务以及Future和callable等详细介绍,4.高并发容器和阻塞容器 ...
- Java并发包——使用新的方式创建线程
Java并发包--使用新的方式创建线程 摘要:本文主要学习了如何使用Java并发包中的类创建线程. 部分内容来自以下博客: https://www.cnblogs.com/dolphin0520/p/ ...
- Java 高并发第三阶段实战---Java并发包深入解析与使用详解
第三阶段的课程主要围绕着Java并发包的使用,展开详细的介绍,主要内容有1.原子包源码剖析,2.并发包工具类详细介绍,3.线程服务以及Future和callable等详细介绍,4.高并发容器和阻塞容器 ...
- java并发包线程池原理分析锁的深度化
java并发包&线程池原理分析&锁的深度化 并发包 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素 ...
- Java多线程并发编程--Java并发包(JUC)
Java多线程并发–Java并发包(JUC) 前言 前一篇文章中,笔者已经介绍了Java多线程的一些基础知识,但是想要成为一名中高级Java程序员还必须懂得Java并发包(JUC)的知识点,而且JUC ...
- java并发中ExecutorService的使用
文章目录 创建ExecutorService 为ExecutorService分配Tasks 关闭ExecutorService Future ScheduledExecutorService Exe ...
- Java并发包--线程池框架
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509903.html 线程池架构图 线程池的架构图如下: 1. Executor 它是"执行者 ...
最新文章
- setup.py安装
- box-sizing 属性
- centos mysql卸载重装_提高性能,MySQL 读写分离环境搭建
- java恶意小程序_小程序java实现校验一张图片是否含有违法违规内容security.imgSecCheck...
- linux fedora安装flameshot火焰截图
- python和javascript哪个好_JavaScript与Python:主要区别
- php底层实现也是c语言,深入php内核,从底层c语言剖析php实现原理
- 2017程序员综合素质调研测试
- 2021桂花开得真晚,晚了将近一个月
- 富士施乐Fuji Xerox DocuPrint CP215 w 驱动
- 发出商品杀手锏之SAP在途库存解决方案
- 仙侣情缘之麒麟劫java_《仙侣情缘之麒麟劫》详细流程攻略[多图]
- 用Java写数据结构作业——7-1 拯救007
- 你真的了解前端模块化吗?
- 一个点击率10万+的恶搞程序送给大家!
- 迪赛智慧数——饼图(玫瑰饼图):世界厨师日之-从业时间
- “双减”政策下的少儿编程市场:前8月融资12起,资本加持下何时跑出“独角兽”?...
- 2018最受欢迎开源免费CMS建站系统排行榜
- 音乐的格式、选择和音质说明
- js知道年月日怎么获取到是周几,和几月几号