`
C_J
  • 浏览: 128134 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Common Pool对象池的中断策略和ThreadPoolExecutor中断策略

阅读更多

题记:

     看到摊子里gogole_09同学分享了他阿里的面筋,其中有个问题提到:线程池的中断策略有哪些?各有什么特点?想想自己也看过Common的对象池源码和用过Sun的ThreadPoolExecutor线程池,却没注意到“中断策略”,这是一个所有缓存池需要考虑的异常问题。

 

Common Pool中断策略

    竟然是中断策略,直接看Common Pool中的borrowObject,从池中取对象,当没有可用的对象的时候的策略。

   

    **StackObjectPool(以Stack为存储结构的Pool)

   

   public synchronized Object borrowObject() throws Exception {
     ....
    Object obj = null;// 取对象
   ...
     obj = _factory.makeObject(); // 制造对象
     newlyCreated = true;
     if (obj == null) {
                    throw new NoSuchElementException("PoolableObjectFactory.makeObject() returned null.");
                  }
     ....
     _numActive++;
     return obj;

 

发现_factory.makeObject(); 这个方法是一个abstract,所以猜测Common Pool并未实现自己的中断策略,而由使用者自行扩展。

 

 

ThreadPoolExecutor中断策略

    JDK提供了4种策略,分别是:

    1、CallerRunsPolicy

    2、AbortPolicy 中止任务

    3、DiscardPolicy 丢弃任务

    4、DiscarOldestPolicy 丢弃最老任务

 

分析中断策略,直接查看ThreadPoolExecutor类中的execute(Runnable command)设计,如下:

 /**
     * The default rejected execution handler
     */
private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();
....
public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        for (;;) {
            if (runState != RUNNING) {
                reject(command);
                return;
            }
            if (poolSize < corePoolSize && addIfUnderCorePoolSize(command))
                return;
            if (workQueue.offer(command))
                return;
            Runnable r = addIfUnderMaximumPoolSize(command);// 当线程大小超过maximumPoolSize时,返回null
            if (r == command)
                return;
            if (r == null) {
                reject(command);// 执行中断策略
                return;
            }
            // else retry
        }
    }

 

reject方法为:

void reject(Runnable command) {
        handler.rejectedExecution(command, this);// 直接调用接口RejectedExecutionHandler的rejectedExecution方法
}

 

4种中断策略的实现,首先,默认的AbortPolicy implements RejectedExecutionHandler

 public static class AbortPolicy implements RejectedExecutionHandler {
        public AbortPolicy() { }

        /**
         * Always throws RejectedExecutionException.
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always.
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException();// 直接抛出异常
        }
    }

 这种策略会让程序抛出异常,会一定程度影响系统运行。

 

然后CallerRunsPolicy策略:

public static class CallerRunsPolicy implements RejectedExecutionHandler {
        public CallerRunsPolicy() { }

        /**
         * Executes task r in the caller's thread, unless the executor
         * has been shut down, in which case the task is discarded.
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {// 只要ThreadPoolExecutor没有关闭,就马上执行新线程,注意这里是run,而非start,新线程会立马执行
                r.run();
            }
        }
    }

 这个策略比较保守,不抛出异常,也不忽略线程,而是让线程直接运行抢占CPU而发生阻塞。

 

DiscardPolicy策略(忽略当前线程):

public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a <tt>DiscardPolicy</tt>.
         */
        public DiscardPolicy() { }

        /**
         * Does nothing, which has the effect of discarding task r.
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {// 直接忽略
        }
    }

这种策略被忽略,而不给出任何警告信息。

 

最后一个DiscardOldestPolicy策略(忽略最老线程)

 public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        public DiscardOldestPolicy() { }

        /**
         * Obtains and ignores the next task that the executor
         * would otherwise execute, if one is immediately available,
         * and then retries execution of task r, unless the executor
         * is shut down, in which case task r is instead discarded.
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();// 直接移除当前队列中头节点
                e.execute(r);// 把新线程加入到队列的尾节点,并调用线程的start方法启动
            }
        }
    }

 

结论:

从代码中看:

    当线程数量小于pool中活动线程数,则创建新线程;

    当线程数量等于pool中活动线程数,则尝试把任务加入到任务队列里面;

    当任务队列满的时候,则执行中断策略进行调整。

    各自的策略都有不同的特点,根据系统的需求选择合适的策略以达到线程利用率的最优。

 

分享到:
评论

相关推荐

    关于java对象池的例子代码

    Java对象池是一种优化资源管理的技术,它通过复用已经创建并初始化过的对象,避免了频繁地创建和销毁对象带来的性能开销。在Java中,对象池通常用于数据库连接、线程、Socket等昂贵资源的管理。下面我们将深入探讨...

    对象池&线程池&数据库连接池

    对象池、线程池和数据库连接池都是资源复用机制的实例,它们有效地解决了频繁创建和销毁对象带来的开销,提高了系统的效率。以下是对这些概念的详细解释: 1. **对象池**: 对象池是一种设计模式,它的核心思想是...

    commons-pool-1.4.jar

    Apache Commons Pool 提供了两种主要的对象池实现:GenericObjectPool 和 GenericKeyedObjectPool。它们都是基于策略的池化框架,允许用户自定义池的行为,例如最大池大小、空闲超时、测试对象是否有效等。这些策略...

    ThreadPoolExecutor使用和思考

    ThreadPoolExecutor使用和思考

    java 线程池例子ThreadPoolExecutor

    ThreadPoolExecutor 的核心参数包括 corePoolSize、maxPoolSize 和 keep-alive time。 * corePoolSize: 表示线程池的核心线程数。这是线程池的基本容量,表示线程池中总是存在的线程数。 * maxPoolSize: 表示线程池...

    线程池实例:使用Executors和ThreadPoolExecutor

    NULL 博文链接:https://bijian1013.iteye.com/blog/2284676

    redis lits queue 和 ThreadPoolExecutor 结合

    - **线程池配置**:根据系统资源和需求,合理配置ThreadPoolExecutor的参数,如核心线程数、最大线程数、队列容量和超时策略等。 5. **优点**: - **解耦**:将任务存储和执行分开,使得系统更灵活,易于扩展。 ...

    线程池之ThreadPoolExecutor.docx

    - `handler`: 饱和策略,当线程池无法接受新任务时的处理方式,包括AbortPolicy、CallerRunsPolicy、DiscardPolicy和DiscardOldestPolicy等。 例如,创建一个固定大小的线程池可以使用`Executors....

    Java--pool-technology.rar_theory

    Java对象池技术是一种优化资源管理的方法,主要用于减少创建和销毁对象的开销,尤其是在频繁创建和销毁对象的应用场景中。其基本思想是预先创建并维护一组可重用的对象,当程序需要一个对象时,可以从池中获取,而...

    ThreadPoolExecutor源码解析.pdf

    了解ThreadPoolExecutor的这些核心概念和工作流程,能帮助开发者更好地调整线程池参数,优化并发性能,以及在系统出现问题时进行排查和定位。在实际开发中,合理配置线程池参数,避免线程池过载,是保障系统稳定运行...

    ThreadPoolExecutor的使用和Android常见的4种线程池使用介绍

    ThreadPoolExecutor的使用和Android常见的4种线程池使用介绍

    ThreadPoolExecutor源码解析.md

    ThreadPoolExecutor源码解析.md

    BlockingPool:线程安全对象池。 当请求资源但池对象已用尽时,发生阻塞

    BlockingPool 常见于数据库连接池(如 C3P0、HikariCP)、线程池和对象池等场景,它有效地解决了资源有限和多线程并发访问的问题。 8. **源码分析** `BlockingPool-master` 压缩包可能包含了 BlockingPool 的实现...

    ThreadPoolExecutor线程池的使用方法

    ThreadPoolExecutor线程池提供了灵活的线程管理机制,可以根据需要选择合适的任务队列和拒绝策略,并且可以自定义线程工厂和线程工具类,从而满足不同应用场景的需求。 ThreadPoolExecutor的使用方法可以分为以下几...

    PyQt5中多线程模块QThread和线程池ThreadPoolExecutor解决PyQt5界面程序执行比较耗时操作无响应问题

    1.资源简介:PyQt5中使用多线程模块QThread解决了PyQt5界面程序执行比较耗时操作时,程序卡顿出现的无响应以及界面输出无法实时...2.适用人群:想学习PyQt5中多线程模块QThread和线程池ThreadPoolExecutor知识的人。

    线程池:java_ThreadPoolExecutor.mht

    (转)线程池:java_util_ThreadPoolExecutor 比较详细的介绍了ThreadPoolExecutor用法与属性

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

    "JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor)使用" JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor)使用是Java多线程编程中的一种重要概念。随着多线程编程的普及,线程池的使用变得...

    ThreadPoolExecutor运转机制介绍

    在Java并发编程中,`ThreadPoolExecutor` 是一种强大的工具,它可以帮助开发者有效地管理和执行线程。`ThreadPoolExecutor` 提供了一种灵活的方式来配置线程池,通过控制线程的数量、队列的行为以及对超出容量的任务...

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

    线程池ThreadPoolExecutor使用简介与方法实例 线程池ThreadPoolExecutor是Java并发编程中...ThreadPoolExecutor是Java并发编程中一个非常重要的概念,它可以帮助我们更好地处理任务,从而提高系统的可扩展性和灵活性。

Global site tag (gtag.js) - Google Analytics