首页 / JAVA / 理解java中的线程池
理解java中的线程池
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了理解java中的线程池,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4592字,纯文字阅读大概需要7分钟。
内容图文
![理解java中的线程池](/upload/InfoBanner/zyjiaocheng/1171/9a7ce83d062743f189712e54dbf05d93.jpg)
1.引入线程池的原因
对于多线程编程,处理每个请求都要创建一个线程,这不仅要花费时间在创建线程的过程中,还会出现创建线程过多未释放导致的系统内存不足,内存溢出问题,因此引入线程池的概念。线程池,就是在一个容器中创建适量的线程,在程序访问的时候直接调用该线程即可访问。
2.类比数据库连接池。
数据库连接池与线程池类似,dao层访问数据库时,首先会,加载驱动,建立连接,而每次频繁的建立连接肯定会大大降低系统运行效率,因此,数据库连接池出现了,下面以一张图进行说明:
如上图,没连接池时访问一次数据库便建立一个Connection,用完,连接释放,添加数据库连接池后,是连接先建立好或者使用时建立,用完,不释放,而是放在数据库连接池中,供下一次请求调用。
3.线程池的执行流程
在具体了解线程池之前,有必要先了解一下,线程池的执行流程。
<1>.当提交一个新任务到线程池中时,先判断线程池中的当前线程数是否大于线程池基本大小(corePoolSize),小于corePoolSize:创建一个新任务来执行当前线程。
<2>.大于corePoolSize,将任务存放入阻塞队列中(假定此时的阻塞队列是有界的),阻塞队列未满:存放入阻塞队列,等待线程执行。
<3>队列已满:判断线程池中的线程数量是否大于maximumPoolSize(线程池的最大容量),小于,创建新线程来处理该任务。
<4>线程池中的线程数量大于maximumPoolSize(线程池的最大容量),即线程池中的所有线程都处于工作状态,此时任务会被拒绝,会交给饱和策略来进行处理。
4.了解java.util.concurrent包下的ThreadPoolExecutor类
ThreadPoolExectuor类是线程池的核心类,其可以创建线程池。
<1> 构造方法(创建线程池时使用):
public
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue);
publicThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory);
publicThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler);
publicThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler);
参数:
corePoolSize - 池中所保存的线程数,包括空闲线程,线程池中的基本线程数。
maximumPoolSize - 池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。即放在阻塞队列中的线程的最大等待时间,
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的阻塞队列。此队列仅保持由 execute 方法提交的 Runnable 任务。
threadFactory - 执行程序创建新线程时使用的工厂。
handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序,拒绝执行任务时的策略。
<2>主要方法:
1》public void execute(Runnable command):向线程池提交一个任务 command,交由线程池去执行。若执行失败则会调用RejectedExecutionHandler,拒绝执行任务策略进行处理。
具体源码:
public
void
execute(Runnable command) {
if (command == null)
thrownew NullPointerException();
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
elseif (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated
}
}
execute方法就是按照上面的线程执行流程来的,
《2 submit 和execute()一样,用于向线程池提交任务,
区别:submit提交具有返回值的任务,execute()无返回值。
《3 shutdown,shutdownNow
区别:主要在是否关闭正在执行的线程。
shutdown:逐个遍历线程池中的线程,调用中断处理,中断没有正在执行的线程。
shudownNow:将线程池的状态设置为stop,停止所有正在执行或停止任务的线程。
5.几种类与接口间的继承,实现关系图
类ThreadPoolExecutor继承类AbstractExecutor
类AbstractExecutor实现接口ExecutorService接口
ExecutorService接口继承Executor接口
6.几种具ThreadPoolExecutor
<1>FixedThreadPool,可重用固定线程数的线程池
其创建过程调用 ThreadPoolExecutor的构造方法
public
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
其中:
corePoolSize, maximumPoolSize为一个具体的固定的值。
keepAliveTime:0L,即多余空闲线程等待新任务的时间为0s,线程池中若存在空闲线程,则会立即被终止。
这儿阻塞队列,采用了LinkedBlockingQueue无界阻塞队列(队列的最大容量为Integer.MAX_VALUE)。
采用无界队列带来的影响:
1.线程池中的正在执行的线程数目不会超过corePoolSize
原因:超过corePoolSize,便会放在阻塞队列中等待被执行,阻塞队列永远不会满,不会再创建新的线程来执行任务。
2.maximumPoolSize,线程池中的最大线程数成为无用参数。很好理解。
3.FixedThreadPool,永远不会拒绝任务,不会使用上面说的几种拒绝策略。(永远不会达到线程池的最大线程数目)
<2>SingleThreadPool(单个线程池)
调用ThreadPoolExecutor的构造方法:
public
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
其中:
corePoolSize, maximumPoolSize 设置为1,使用单个线程。
keepAliveTime:0L,即多余空闲线程等待新任务的时间为0s,线程池中若存在空闲线程,则会立即被终止。
这儿阻塞队列,采用了LinkedBlockingQueue无界阻塞队列,单个线程无限反复的从阻塞队列中拿出任务进行执行。
同样无界队列带来的问题,SingleThreadPool也有。
<3>.CachedThreadPool(按需分配的线程池)
调用ThreadPoolExecutor的构造方法:
public
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
其中:
corePoolSize,默认设置为0,
maximumPoolSize ,设置Integer.MAX_VALUE,即线程池的最大线程数是无界的。
keepAliveTime:60L,即多余空闲线程等待新任务的时间为60s,
这儿阻塞队列,采用了SynchronousQueue无界阻塞队列,SynchronousQueue:一个没有容量的阻塞队列,在插入之前必须有线程从队列中拿走的操作,
CachedThreadPool:按需分配的线程池,就是主线程offer任务1,线程池中查找有无空闲线程,无则创建新线程让其执行任务1,同时,任务2来了,查看有空闲线程,让其执行任务2,还有空闲线程,等待60s若还没有任务执行,则终止。
具体实践:
1.线程池应用之自主实现一个线程池
2.使用Executors中提供的线程池实现生产者-消费者模型
参考自:java并发编程的艺术(方腾飞)
原文:http://blog.csdn.net/wangpei555/article/details/70314804
内容总结
以上是互联网集市为您收集整理的理解java中的线程池全部内容,希望文章能够帮你解决理解java中的线程池所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。