十分钟了解线程池,阿里再也不用担心我瞎用线程池了

线程池:避免了创建线程和销毁线程的资源损耗。

Executors提供四种线程池:

newCachedThreadPool :缓存线程池,如果线程池长度超过处理需要,可回收空闲线程,若无可回收,则新建线程。

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

newScheduledThreadPool : 计划线程池,支持定时及周期性任务执行。

newSingleThreadExecutor :单线程线程池,用唯一的线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

先了解下线程池必备的以下几个属性:

poolSize : 当前程序运行的线程数。

coreSize:  核心线程数。

MaximumPoolSize: 线程池中最大线程数。

keepAliveTime:线程空闲时间超过,则会超时退出。

BlockingQueue :设置一个阻塞用来存放将要执行的等待任务。

(线程安全:保证取队列元素时一个只能取一个,且头元素没有时不能取,满时不能加入)

线程池的运行流程:

当需要执行一个任务时:

poolsize < coresize ->开启一个新的线程执行

poolsize = coresize && 队列未满  -> 这时已经达到了核心线程数,线程不够了,加入到阻塞队列中,慢慢执行。

Poolsize < MaximumPoolSize && 队列已满  -> 这时队列都满了,那不行啊 ,快爆了,在开启一个新线程吧。

(通常超出核心线程的线程是“借”的,也就是说超出核心线程的情况算是一种能够预见的异常情况,并且这种情况并不常常发生(如果常常发生,那我想你应该调整你的核心线程数了)

Poolsize = MaximumPoolSize  && 队列满了 -> 已经所有办法用尽了,会根据饱和策略RejectedExecutionHandler拒绝新的任务。

(如果设置了keepAliveTime,可以通过以下配置来确定小于corePoolSize时,是否启动超时处理。

但是对于超出MaximumPoolSize,一定会进行超时处理,因为这些线程本就不是正常情况。

allowCoreThreadTimeOut:是否允许核心线程超时退出。

如果该值为false(默认),且poolSize<=corePoolSize,线程池都会保证这些核心线程处于存活状态,不会超时退出。(所以只要不是超过corePoolSize,线程都会空闲而不是销毁)

如果为true,则不论poolSize的大小,都允许超时退出。

如果poolSize>corePoolSize,则该参数不论true还是false,都允许超时退出。

)

(所以大概流程:执行一个任务,如果线程少于coresize则启动新线程,如果等于了coresize,则加入队列等待。如果队列满了,实再不行了,则在开启新线程。如果线程等于最大线程了,执行饱和策略拒绝任务)

自定义线程:可以发现,其实就是我们说的那几个参数,特别简单。

public ThreadPoolExecutor(int corePoolSize,

                         int maximumPoolSize,

                         long keepAliveTime,

                         TimeUnit unit,

                         BlockingQueue<Runnable> workQueue)


/**

*coresieze和maximumPool相同,所以这也是为什么他是固定大小。

并且阻塞LinkedBlockingQueue没有初始化大小,是个无界队列。所以进来的任务,线程不够就会都加入队列等待。

keepAliveTime:0,默认超过最大线程才会启用超时,意味着:一超过最大线程数,立即关闭。

*/

public static ExecutorService newFixedThreadPool(int nThreads) {

       return new ThreadPoolExecutor(nThreads, nThreads,

                                     0L, TimeUnit.MILLISECONDS,

                                     new LinkedBlockingQueue<Runnable>());

   }


/**

* coresieze和maximumPool都为1

*/

public static ExecutorService newSingleThreadExecutor() {

       return new FinalizableDelegatedExecutorService

           (new ThreadPoolExecutor(1, 1,

                                   0L, TimeUnit.MILLISECONDS,

                                   new LinkedBlockingQueue<Runnable>()));

   }


/**

* 核心线程为0,最大线程数无限大。意味着,所有线程都有keepalivetime,都有一小段的生命周期。(缓存线程也就是说,执行的线程会缓存一段时间,然后到时间释放)在使用这类无限大的线程池时,非常容易内存消耗殆尽。这也是为什么阿里不建议使用Executors创建线程池。其实自定义线程池非常好用,而且自己看了就会非常明确。

SynchronousQueue(同步队列)一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作(即每个任务都必须有线程接管,否则不加入),否则插入操作一直处于阻塞状态

*/

public static ExecutorService newCachedThreadPool() {

       return new ThreadPoolExecutor(0, Integer.MAX_VALUE,

                                     60L, TimeUnit.SECONDS,

                                     new SynchronousQueue<Runnable>());

   }


/**

*定时线程使用的是ThreadPoolExecutor子类

*/

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {

       return new ScheduledThreadPoolExecutor(corePoolSize);

   }

public static ScheduledExecutorService newSingleThreadScheduledExecutor() {

       return new DelegatedScheduledExecutorService

           (new ScheduledThreadPoolExecutor(1));

   }


线程池拒绝策略:

当线程池满了,队列也满了,这时候需要执行拒绝策略。默认策略感觉不太好,如果一满就会报异常停止运行。

AbortPolicy(默认)

默认策略,直接跑出异常阻止系统正常运行

CallerRunsPolicy

“调用者运行”一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将任务回馈至调用方,比如main线程

DiscardOldestPolicy

抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务

DiscardPolicy

直接丢弃任务,不给予任何处理也不跑出异常,如果允许任务丢失

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358

推荐阅读更多精彩内容