Java线程池排队策略 & 拒绝策略

1、为什么JDK1.5引入线程池

在Java中,如果每个任务都创建一个新的thread,开销是非常大的。除了创建和销毁线程的时间开销外,还消耗大量的系统资源。为了规避以上问题,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利用已有的线程对象来进行服务,这就是线程池引入的原因。 

2、ThreadPoolExecutor类分析

(a)ThreadPoolExecutor构造函数:



public ThreadPoolExecutor(int corePoolSize,

  int maximumPoolSize,

  long keepAliveTime,

  TimeUnit unit,

  BlockingQueue<Runnable> workQueue,

  ThreadFactory threadFactory,

  RejectedExecutionHandler handler);


1)corePoolSize 核心线程数 

(2)maximumPoolSize 最大线程数

(3)keepAliveTime 线程被回收前的空闲时间

(4)workQueue 任务队列

(5)threadFactory 线程创建工厂

(6)handler 线程池对拒绝任务的处理策略

(b)ThreadPoolExecutor运行原理:

ThreadPoolExecutor将根据corePoolSize和maximumPoolSize设置的值调整线程池大小。当新任务调用方法execute(Runnable)提交时,如果运行的线程少于corePoolSize,则创建新线程来处理请求。如果正在运行的线程数等于corePoolSize时,则新任务被添加到队列中,直到队列满。当队列满了后,会继续开辟新线程来处理任务,但不超过最大线程数。当任务队列满了并且已开辟了最大线程数,此时又来了新任务,ThreadPoolExecutor会拒绝服务。

(c)keepAliveTime注意事项:



/**

* Timeout in nanoseconds for idle threads waiting for work.

* Threads use this timeout when there are more than corePoolSize

* present or if allowCoreThreadTimeOut. Otherwise they wait

* forever for new work.

*/

private volatile long keepAliveTime;



说明:当线程空闲超过keepAliveTime,非核心线程会被回收,若allowCoreThreadTimeOut为true则核心线程也会被回收。



/**

* If false (default), core threads stay alive even when idle.

* If true, core threads use keepAliveTime to time out waiting

* for work.

*/

private volatile boolean allowCoreThreadTimeOut;



说明:默认情况下,核心线程不会被回收;当allowCoreThreadTimeOut为true,核心线程也会被回收。

3、任务队列

BlockingQueue<Runnable> workQueue;

workQueue是一个BlockingQueue接口的对象,仅用于存放Runnable对象。

(1)直接提交(如SynchronousQueue)

直接提交策略表示线程池不对任务进行缓存。新进任务直接提交给线程池,当线程池中没有空闲线程时,创建一个新的线程处理此任务。这种策略需要线程池具有无限增长的可能性。

Executors.newCachedThreadPool()使用SynchronousQueue创建线程池。

(2)无界队列(如不具有预定义容量的LinkedBlockingQueue)

LinkedBlockingQueue将导致当所有 corePoolSize 线程都忙时新任务在队列中等待。这样,创建的线程就不会超过 corePoolSize。(因此,maximumPoolSize 的值也就无效了。)当每个任务完全独立于其他任务,即任务执行互不影响时,适合于使用无界队列。

Executors.newFixedThreadPool(3)使用LinkedBlockingQueue创建线程池。

Executors.newSingleThreadExecutor()使用LinkedBlockingQueue创建线程池。

(3)有界队列(如ArrayBlockingQueue)

有界队列(如ArrayBlockingQueue)有助于防止资源耗尽当最大线程数有限时,但是可能较难调整和控制。队列大小和最大池大小可能需要相互折衷。

(4)优先级队列(如PriorityBlockingQueue)

(5)DelayedWorkQueue

DelayedWorkQueue是ScheduledThreadPoolExecutor的静态内部类。

Executors.newScheduledThreadPool(3)使用DelayedWorkQueue创建线程池。

4、拒绝策略

接口RejectedExecutionHandler提供了拒绝任务处理的自定义方法的机会。在ThreadPoolExecutor中已经包含四种拒绝策略。

(1)AbortPolicy

拒绝策略:抛出运行时异常RejectedExecutionException。

这种策略丢弃任务,并抛出异常。(jdk默认策略)

(2)DiscardPolicy

拒绝策略:不能执行的任务将被丢弃。

这种策略什么都没做。

(3)DiscardOldestPolicy

拒绝策略:如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序。



public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

    if (!e.isShutdown()) {

        e.getQueue().poll();

        e.execute(r);

    }

}



该策略稍微复杂一些,在pool没有关闭的前提下首先丢掉缓存在队列中的最早的任务,然后重新尝试运行该任务。

(4)CallerRunsPolicy

拒绝策略:线程调用运行该任务的 execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。



public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

    if (!e.isShutdown()) {

        r.run();

    }

}


这个策略不想放弃执行任务。但是由于池中已经没有任何资源了,那么就直接使用调用该execute的线程本身来执行。

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

推荐阅读更多精彩内容

  • 一.Java中的ThreadPoolExecutor类 java.uitl.concurrent.ThreadPo...
    谁在烽烟彼岸阅读 625评论 0 0
  • 第一部分 来看一下线程池的框架图,如下: 1、Executor任务提交接口与Executors工具类 Execut...
    压抑的内心阅读 4,197评论 1 24
  • 我发表在简书上的文章,阅读量402。 换了个题目,在公众号上的阅读量17817。哎呀,哎呀,哎呀呀呀,这做人的差距...
    春秋半步阅读 630评论 9 3
  • 爱情,顾名思义,因爱产生的感情。古往今来,多少诗词围绕着爱情产生。凄美哀怨的,此情无计可消除,才下眉头,却上...
    我这半辈子阅读 315评论 5 1
  • 生活总是这样不能如意,也许老天给你关上一扇窗的时候就会给你打开一扇门,五年,不长但在自己看来却也是不短的...
    A贝贝家微店阅读 266评论 0 2