前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java 线程池简介

java 线程池简介

作者头像
DencyCheng
发布2019-10-25 11:56:36
5240
发布2019-10-25 11:56:36
举报
文章被收录于专栏:SpringBootSpringBoot

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/qq_32534855/article/details/99608297

简介

什么是“池” : 软件中的“池”,可以理解为计划经济时代的工厂。 首先,作为工厂,你要管理好你生产的东西,老王从你工厂这里拿走了一把斧头,改天他不需要了,还回来,你可以把这把斧头借给老赵; 其次,你又不能无限制的生产,毕竟在资源极度匮乏的时代,如果都被你拿去生产了,其他要用到资源的地方怎么办? 总结成两点,“池”的作用: 复用已有资源 控制资源总量 数据库连接池是这样,线程池也是如此。 你一个任务过来了,我发现池子里有没事干并且还活着的线程,来,拿去用,我也不用费事给你创建一条线程了,要知道线程的创建和销毁可都是麻烦事; 你一个任务过来了,我发现池子的线程都在忙,并且现在池子的线程已经太多了,再不限制下去就要内存溢出了,来,排队去~

Java中常见的4种线程池:

1    FixedThreadPool 2    CachedThreadPool 3    ScheduledThreadPool 4    SingleThreadExecutor

FixedThreadPool: 固定线程数的线程池,可控制线程最大并发数,超出的线程会在队列中等待。

这里的线程数是固定的,每个线程都会从任务队列中去取任务,由于这个取的动作是并发的,所以要求任务队列具有线程安全的特性,所以通常会使用阻塞队列来实现。

CachedThreadPool: 可缓存线程池(特点: 无界线程池,具有自动回收多余线程的功能)

在这种情况下,我们的线程数量并不是固定的,而且我们也没有一个用来存储已提交任务的队列;相反,这种线程池用有一个同步队列(synchronous queue),它只能存储1个Task。每当我们提交了一个任务给线程池,这个任务就会被放到这个队列中。此时,线程池会在已经创建的所有线程中去寻找空闲的线程,并把这一个任务交给这个空闲的线程去执行。如果线程池没能找到一个空闲的线程,说明所有的线程都在工作,那么它就会新建一个线程,并把这个任务交给这个刚刚创建好的线程去执行,这样就达到了动态增加线程数量的目的。

ScheduledThreadPool 支持定时及周期性任务执行的线程池。

这种线程池是专门服务于需要延迟或周期执行任务的场景,例如我们需要每10秒进行一次安全检查。  ScheduledThreadPool主要有3种执行任务的方法:  1.    service.schedule 延迟且单次执行,例如10秒后执行,总共只执行一次  2.    service.scheduleAtFixedRate 每间隔固定时间执行一次,例如每10秒执行一次  3.    service.scheduleAtFixedDelay 在上一个任务执行后,间隔固定时间再次执行。例如:每个Task需要执行5分钟,那么我们可以设定在这个Task直接结束后,等待1分钟再执行下一次的任务,所以最终的效果就是每6分钟该任务会被执行一次。  scheduleAtFixedRate和scheduleAtFixedDelay的区别在于,scheduleAtFixedRate是以任务开始执行的时间为起点,开始计时,而scheduleAtFixedDelay是以任务执行完毕为时间起点进行计时。

这里用来存储Task的queue是一个延迟队列,延迟队列的特点是:不是先进先出,而是会按照延迟时间的长短来排序,下一个即将执行的任务会排到队列的最前面。我们来举个例子:例如我们往这个队列中,放一个延迟10分钟执行的任务,然后再放一个延迟10秒钟执行的任务。通常而言,如果不是延迟队列而是普通队列,那么按照先进先出的排列规则,也就是第一个放置的会排在最前面,也就是延迟10分钟执行的那个任务会放在最前面,但是由于我们此时使用的是延迟队列,延迟队列在排放各个任务的位置的时候,会根据延迟时间的长短来排放。所以。我们第二个放置的延迟10秒钟执行的那个任务,反而会排在延迟10分钟的任务的前面,因为它的执行时间更早。

SingleThreadExecutor 单线程的线程池:它只会用唯一的工作线程来执行任务,它的原理和FixedThreadPool是一样的,但是此时的线程数量被设置为了1。这里的这一个线程,会不停地从任务队列里取任务,然后执行。如果线程在执行任务的时候,遇到了异常导致线程执行中断,那么线程池会重新创建一个线程继续执行后续的任务,而不会永远地中断执行任务。

使用场景:目的是保证所有任务按照提交任务的顺序执行。例如我们想要让第二个任务必须在第一个任务之后执行,同理,或者我们希望让任务三在任务二之后执行,这种场景下就需要用到SingleThreadExecutor。因为执行任务的线程只有一个,所以我们可以保证执行的顺序,而之前那几种线程池在执行的时候,由于有多个线程同时执行,所以我们不能保证各个任务之间的执行顺序。

以上4种线程池的构造函数的参数: 其中fixedThreadPool的keepAliveTime是0秒,这里的0代表永久,也就是fixedThreadPool不会kill任何一个idle的线程,即便该线程无事可做(不执行Task)。 newCachedThreadPool的参数指定了corePoolSize为0,所以CachedThreadPool在最开始的时候并不会创建线程,直到有Task进来,需要线程工作的时候才会创建线程。而可以看出CachedThreadPool的maxPoolSize的值是Integer.MAX_VALUE,这可能会创建数量非常多的线程,甚至导致OOM。 ScheduledThreadPool和SingleThreadPool也是同理。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-08-14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档