`
bugyun
  • 浏览: 556229 次
社区版块
存档分类
最新评论

ThreadPoolExecutor中keepAliveTime及拒绝策略

 
阅读更多

 

转自:http://dongxuan.iteye.com/blog/902571

 

 

工作中多处接触到了ThreadPoolExecutor。趁着现在还算空,学习总结一下。

 

前记:

 

  1. jdk官方文档(javadoc)是学习的最好,最权威的参考。
  2. 文章分上中下。上篇中主要介绍ThreadPoolExecutor接受任务相关的两方面入参的意义和区别,池大小参数corePoolSize和maximumPoolSize,BlockingQueue选型(SynchronousQueue,LinkedBlockingQueue,ArrayBlockingQueue);中篇中主要聊聊与keepAliveTime这个参数相关的话题;下片中介绍一下一些比较少用的该类的API,及他的近亲:ScheduledThreadPoolExecutor
  3. 如果理解错误,请直接指出。
 
===============================神奇分割线==================================
 
通过上篇文章,我们可以总结出:ThreadPoolExecutor中额定的“工人”数量由corePoolSize决定,当任务数量超过额定工人数量时,将任务缓存在BlockingQueue之中,当发现如果连queue中也放不下时(可能是因为使用有界queue,也可能是使用SynchronousQueue),ThreadPoolExecutor会请求“老板”再派几个“工人”过来
 
接下来发生的事情有两种情况:
  1. 任务不再过来了 - keepAliveTime
  2. 任务仍然继续过来 - RejectedExecutionHandler
 
===============================神奇分割线==================================
 
keepAliveTime
 
jdk中的解释是:当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
 
有点拗口,其实这个不难理解,在使用了“池”的应用中,大多都有类似的参数需要配置。比如数据库连接池,DBCP中的maxIdle,minIdle参数。
 
什么意思?接着上面的解释,后来向老板派来的工人始终是“借来的”,俗话说“有借就有还”,但这里的问题就是什么时候还了,如果借来的工人刚完成一个任务就还回去,后来发现任务还有,那岂不是又要去借?这一来一往,老板肯定头也大死了。
 
合理的策略:既然借了,那就多借一会儿。直到“某一段”时间后,发现再也用不到这些工人时,便可以还回去了。这里的某一段时间便是keepAliveTime的含义,TimeUnit为keepAliveTime值的度量。
 
RejectedExecutionHandler
 
另一种情况便是,即使向老板借了工人,但是任务还是继续过来,还是忙不过来,这时整个队伍只好拒绝接受了。
 
RejectedExecutionHandler接口提供了对于拒绝任务的处理的自定方法的机会。在ThreadPoolExecutor中已经默认包含了4中策略,因为源码非常简单,这里直接贴出来。
 
CallerRunsPolicy线程调用运行该任务的 execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。
 
Java代码  收藏代码
  1. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {  
  2.             if (!e.isShutdown()) {  
  3.                 r.run();  
  4.             }  
  5.         }  
 
这个策略显然不想放弃执行任务。但是由于池中已经没有任何资源了,那么就直接使用调用该execute的线程本身来执行。
 
AbortPolicy:处理程序遭到拒绝将抛出运行时 RejectedExecutionException
 
Java代码  收藏代码
  1. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {  
  2.             throw new RejectedExecutionException();  
  3.         }  
 这种策略直接抛出异常,丢弃任务。
 
DiscardPolicy:不能执行的任务将被删除
 
Java代码  收藏代码
  1. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {  
  2.         }  
 这种策略和AbortPolicy几乎一样,也是丢弃任务,只不过他不抛出异常。
 
DiscardOldestPolicy:如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)
 
Java代码  收藏代码
  1. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {  
  2.             if (!e.isShutdown()) {  
  3.                 e.getQueue().poll();  
  4.                 e.execute(r);  
  5.             }  
  6.         }  
该策略就稍微复杂一些,在pool没有关闭的前提下首先丢掉缓存在队列中的最早的任务,然后重新尝试运行该任务。这个策略需要适当小心。
设想:如果其他线程都还在运行,那么新来任务踢掉旧任务,缓存在queue中,再来一个任务又会踢掉queue中最老任务。
 
总结:
 
keepAliveTime和maximumPoolSize及BlockingQueue的类型均有关系。如果BlockingQueue是无界的,那么永远不会触发maximumPoolSize,自然keepAliveTime也就没有了意义。
 
反之,如果核心数较小,有界BlockingQueue数值又较小,同时keepAliveTime又设的很小,如果任务频繁,那么系统就会频繁的申请回收线程。
分享到:
评论

相关推荐

    JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor)使用

    在上面的示例中,我们使用ThreadPoolExecutor类构造了一个线程池,线程池的corePoolSize为5,maximumPoolSize为10,keepAliveTime为60秒,unit为 TimeUnit.SECONDS,workQueue为ArrayBlockingQueue,handler为...

    ThreadPoolExecutor运转机制介绍

    如果当前线程池中的线程数量已经达到 `maximumPoolSize`,那么将会根据 `RejectedExecutionHandler` 的拒绝策略来处理新任务。 4. **线程的销毁**:当线程池中的线程数量大于 `corePoolSize` 时,那些超过 `...

    Java线程池的拒绝策略实现详解

    在这个示例代码中,我们创建了一个ThreadPoolExecutor实例,并将其配置为使用AbortPolicy拒绝策略。当提交的任务数大于核心线程数和最大线程数之和时,ThreadPoolExecutor将抛出RejectedExecutionException异常信息...

    线程池ThreadPoolExecutor原理源码分析.md

    - 如果放入任务失败或线程池状态发生变化(如变为 `SHUTDOWN`),则采取拒绝策略处理任务。 4. **创建非核心线程**: - 如果任务队列已满或者线程池状态不允许放入新任务,尝试创建非核心线程来立即处理新任务。 ...

    JDK之ThreadPoolExecutor源码分析1

    4. 当线程池中的线程数量超过最大线程数时,线程池将拒绝执行新任务。否则,线程池会创建新的非核心线程来处理任务,但总数不会超过最大线程数。 在分析源码之前,我们需要了解ThreadPoolExecutor构造函数的一些...

    线程池ThreadPoolExecutor使用简介与方法实例

    如果线程池中的线程数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么ThreadPoolExecutor会通过handler所指定的策略来处理任务。 三、线程池ThreadPoolExecutor的方法实例 ...

    使用线程池ThreadPoolExecutor 抓取论坛帖子列表

    总的来说,利用`ThreadPoolExecutor`抓取论坛帖子列表是一种有效的并发策略,它能充分利用系统资源,提高程序性能。通过深入理解线程池的工作机制和源码,我们可以更好地设计和优化我们的并发程序,实现高效的数据...

    线程池ThreadPoolExecutor

    `ThreadPoolExecutor`是线程池的默认实现类,它允许我们自定义线程池的核心参数,如核心线程数、最大线程数、空闲线程存活时间、工作队列和拒绝策略等。`ScheduledThreadPoolExecutor`则用于实现周期性任务调度。 `...

    java线程池

    示例代码`TestThreadPool`创建了一个线程池,其中corePoolSize为2,maximumPoolSize为4,keepAliveTime为3秒,工作队列大小为3,拒绝策略为`ThreadPoolExecutor.CallerRunsPolicy()`。这意味着当工作队列满时,提交...

    线程池使用示例(含源代码)

    在提供的"线程池示例"文件中,应该包含了创建和使用线程池的代码示例,你可以参考并进行扩展,例如添加更多任务、调整线程池参数,或者实现自定义的线程工厂和拒绝策略,以加深对线程池的理解。

    JDK1.5线程池源码及详细注释

    线程池的核心在于它的设计策略,包括核心线程数、最大线程数、线程存活时间、工作队列以及拒绝策略。 线程池的主要类是`ThreadPoolExecutor`,它的构造函数参数定义了线程池的关键特性: 1. `corePoolSize`: ...

    ThreadPoolExecutor线程池原理及其execute方法(详解)

    ThreadPoolExecutor的构造方法中有四个参数:corePoolSize、maximumPoolSize、keepAliveTime和workQueue。 * corePoolSize:核心线程池的线程数量,表示线程池中最少的线程数量。 * maximumPoolSize:最大线程池的...

    JDK1[1].5中的线程池(ThreadPoolExecutor)使用简介.

    corePoolSize: 线程池维护线程的最少数量 maximumPoolSize:线程池维护线程的最大数量 keepAliveTime: 线程池维护线程所允许的空闲时间 unit: 线程池维护线程所允许的空闲...handler: 线程池对拒绝任务的处理策略

    Android之线程池ThreadPoolExecutor的简介

    * handler:当任务数超过maximumPoolSize时,对任务的处理策略,默认策略是拒绝添加 执行流程: 当线程数小于corePoolSize时,每添加一个任务,则立即开启线程执行 当corePoolSize满的时候,后面添加的任务将放入...

    线程池源码

    在`TheadPoolTest1`这个测试文件中,可能包含了对线程池的初始化、任务提交、执行流程跟踪以及各种场景下的测试,比如不同负载情况下的性能比较、拒绝策略的验证等。通过分析这个源码,我们可以深入理解线程池的运作...

    01.java并发编程面试宝典

    2. 将任务提交缓存在并发队列中,如果缓存队列满了,则会执行拒绝策略 3. 正在运行的线程从并发队列中获取任务执行,从而实现多线程复用 _java_ 提供了多种线程池实现,例如 ThreadPoolExecutor、...

    ThreadPoolManager_线程池管理

    以上是对"ThreadPoolManager_线程池管理"的相关知识点的详细阐述,包括线程池的基本概念、ThreadPoolExecutor的使用、拒绝策略、生命周期以及线程池的最佳实践。在实际项目中,合理地使用线程池可以显著提高程序的...

    Android线程池管理的代码例子

    // 拒绝策略 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); ``` ...

Global site tag (gtag.js) - Google Analytics