ThreadPoolExecutor运转机制详解

转载自走向架构师之路

最近发现几起对ThreadPoolExecutor的误用,其中包括自己,发现都是因为没有仔细看注释和内部运转机制,想当然的揣测参数导致,先看一下新建一个ThreadPoolExecutor的构建参数:

[java]  view plain copy
  1. public ThreadPoolExecutor(int corePoolSize,  
  2.                           int maximumPoolSize,  
  3.                           long keepAliveTime,  
  4.                           TimeUnit unit,  
  5.                           BlockingQueue<Runnable> workQueue,  
  6.                           ThreadFactory threadFactory,  
  7.                           RejectedExecutionHandler handler)  

看这个参数很容易让人以为是线程池里保持corePoolSize个线程,如果不够用,就加线程入池直至maximumPoolSize大小,如果还不够就往workQueue里加,如果workQueue也不够就用RejectedExecutionHandler来做拒绝处理。

但实际情况不是这样,具体流程如下:

1)当池子大小小于corePoolSize就新建线程,并处理请求

2)当池子大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去从workQueue中取任务并处理

3)当workQueue放不下新入的任务时,新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize就用RejectedExecutionHandler来做拒绝处理

4)另外,当池子的线程数大于corePoolSize的时候,多余的线程会等待keepAliveTime长的时间,如果无请求可处理就自行销毁

内部结构如下所示:

从中可以发现ThreadPoolExecutor就是依靠BlockingQueue的阻塞机制来维持线程池,当池子里的线程无事可干的时候就通过workQueue.take()阻塞住。

其实可以通过Executes来学学几种特殊的ThreadPoolExecutor是如何构建的。

[java]  view plain copy
  1. public static ExecutorService newFixedThreadPool(int nThreads) {  
  2.     return new ThreadPoolExecutor(nThreads, nThreads,  
  3.                                   0L, TimeUnit.MILLISECONDS,  
  4.                                   new LinkedBlockingQueue<Runnable>());  
  5. }  

newFixedThreadPool就是一个固定大小的ThreadPool

[java]  view plain copy
  1. public static ExecutorService newCachedThreadPool() {  
  2.     return new ThreadPoolExecutor(0, Integer.MAX_VALUE,  
  3.                                   60L, TimeUnit.SECONDS,  
  4.                                   new SynchronousQueue<Runnable>());  
  5. }  

newCachedThreadPool比较适合没有固定大小并且比较快速就能完成的小任务,没必要维持一个Pool,这比直接new Thread来处理的好处是能在60秒内重用已创建的线程。

其他类型的ThreadPool看看构建参数再结合上面所说的特性就大致知道它的特性


ThreadPoolExecutor执行task的方法如下,结合这段代码可以更好理解文章一开始提到的执行流程:

/**
     * Executes the given task sometime in the future.  The task
     * may execute in a new thread or in an existing pooled thread.
     *
     * If the task cannot be submitted for execution, either because this
     * executor has been shutdown or because its capacity has been reached,
     * the task is handled by the current <tt>RejectedExecutionHandler</tt>.
     *
     * @param command the task to execute
     * @throws RejectedExecutionException at discretion of
     * <tt>RejectedExecutionHandler</tt>, if task cannot be accepted
     * for execution
     * @throws NullPointerException if command is null
     */
    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
            if (runState == RUNNING && workQueue.offer(command)) {
                if (runState != RUNNING || poolSize == 0)
                    ensureQueuedTaskHandled(command);
            }
            else if (!addIfUnderMaximumPoolSize(command))
                reject(command); // is shutdown or saturated
        }
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ThreadPoolExecutor 是 Java 提供的用于创建线程池的类,它的构造函数有很多参数,下面是对这些参数的详细解释: 1. corePoolSize:线程池中核心线程的数量。当线程池中的线程数量小于 corePoolSize 时,新的任务会一直创建新的线程直到达到 corePoolSize 个线程。 2. maximumPoolSize:线程池中最大线程数。当线程池中的线程数量达到 corePoolSize 后,新的任务会被放入到等待队列中,等待被执行。如果等待队列已满,且线程池中的线程数量小于 maximumPoolSize,则会创建新的线程执行任务。 3. keepAliveTime:线程池中非核心线程的超时时间。当线程池中的线程数量大于 corePoolSize 时,多余的线程会被回收,但回收前会等待 keepAliveTime 时间,如果在这个时间内没有新的任务需要执行,则这个线程会被终止。 4. TimeUnit:超时时间的单位。 5. workQueue:用于缓存等待执行的任务的队列。ThreadPoolExecutor 提供了多种队列,如 ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue 等。可以根据需求选择不同的队列。 6. threadFactory:用于创建新的线程。ThreadPoolExecutor 默认使用 Executors.defaultThreadFactory() 创建线程。如果需要自定义线程创建方式,可以实现 ThreadFactory 接口。 7. handler:线程池中的线程数量达到 maximumPoolSize,并且等待队列已满时,新的任务的处理策略。ThreadPoolExecutor 提供了 4 种策略: - AbortPolicy:直接抛出异常; - CallerRunsPolicy:不在新线程中执行任务,而是让调用 execute 方法的线程执行任务; - DiscardOldestPolicy:丢弃最老的任务,执行当前任务; - DiscardPolicy:直接丢弃任务。 这些参数可以根据实际需求进行调整,以达到最优的线程池效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值