欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java多线程高并发高级篇(一)--线程池核心详解

程序员文章站 2022-04-03 13:26:09
...

在说核心内容之前,需要问一个问题,既然单个线程的创建和销毁都很简单,我们为什么要使用线程池?

使用池化技术是为了什么?

估计工作过很多年的老鸟们对这些东西都能说出个一二三来,无非就是以下几点:

1、线程相对于进程而言,虽然是轻量级的,但是它的创建依然需要占用我们那点宝贵的内存资源。如果无限制的创建线程,对应垃圾回收而言也是很有压力的,毕竟线程也是对象。使用线程池统一进行线程的调度,便于管理和控制。

2、线程的创建和关闭是需要花费时间的,这点毋庸置疑吧。如果任务非常多,频繁的创建和销毁线程也是需要占用系统的分片时间的,对于系统而言,这点时间对于处理任务的时间来说,有点浪费。

总结一下,使用线程池的目的就是将系统创建的线程进行复用,节约创建和销毁线程带来的时间开销。使用线程池后,创建线程就变成了从线程池获取空闲线程(当然,没有线程的时候也是需要创建的),销毁线程就变成了将线程归还线程池。

创建线程是为了什么?当然是为了处理任务(Task)。

Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
 

 

一、JDK对线程池的支持

JDK提供了一套Executor框架,帮助开发人员有效的进行线程控制。

Executor框架结构图(最好自己画个UML类图,首先需要知道类图中每个符号的意思,这是源码必备的分析方法):


Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
以上涉及到的核心成员类都在java.util.concurrent包下。

上图是全部的UML类图关系,猛然一看,估计你不懵都难。所以,我们抛去依赖关系,得到最简图,这样理解起来就不费劲了。


Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
 那么,我们说的线程池是谁?就是ThreadPoolExecutor。我学习东西喜欢刨根问底,所以,我想问为什么它就是线程池?我们看上图,所有接口的第一个实现类是谁(不算抽象类)?对头,就是ThreadPoolExecutor。ScheduledThreadPoolExecutor扩展了线程池的功能(为什么英文起名字要见名知意,你从Scheduled是不是明白了什么),可以把它作为扩展功能了解。

以上整个代码架构,有人称之为Executor框架(不要一听框架就觉得有多么神奇高大,它就是个名字,因为线程池的一整套代码组织的起源是Executor,往上看下)。

 

二、线程池详解

既然要深究线程池,就不得不去看看源码,毕竟源码才是作者表达意思的代码体现。

我们看下线程池有些什么玩意--我们追踪了这个类中的实现,所有的构造函数,无一例外的都归结到下面最长的这个构造函数上,也就是说,这个构造函数是线程池的核心!


Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
 

/**
     * Creates a new <tt>ThreadPoolExecutor</tt> with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the
     * pool, even if they are idle.
     * @param maximumPoolSize the maximum number of threads to allow in the
     * pool.
     * @param keepAliveTime when the number of threads is greater than
     * the core, this is the maximum time that excess idle threads
     * will wait for new tasks before terminating.
     * @param unit the time unit for the keepAliveTime
     * argument.
     * @param workQueue the queue to use for holding tasks before they
     * are executed. This queue will hold only the <tt>Runnable</tt>
     * tasks submitted by the <tt>execute</tt> method.
     * @param threadFactory the factory to use when the executor
     * creates a new thread.
     * @param handler the handler to use when execution is blocked
     * because the thread bounds and queue capacities are reached.
     * @throws IllegalArgumentException if corePoolSize or
     * keepAliveTime less than zero, or if maximumPoolSize less than or
     * equal to zero, or if corePoolSize greater than maximumPoolSize.
     * @throws NullPointerException if <tt>workQueue</tt>
     * or <tt>threadFactory</tt> or <tt>handler</tt> are null.
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

 

 

 我们详细解释下这些参数的含义:

看参数含义,我们最好不要自己去理解,看的时候要结合英文注释,因为注释部分是作者要表达的真正含义。

①corePoolSize: the number of threads to keep in the pool, even if they are idle.(核心线程池大小:为什么这么起名称,是因为作者想表达的含义是线程池应该保证线程数目会有这么多,不管他们创建以后是不是空闲)。

②maximumPoolSize: the maximum number of threads to allow in the pool.(线程池中允许创建线程的最大数目,啥意思?如果核心线程数已经达到,任务还源源不断的来,那么maximumPoolSize表达的意思就是核心线程数+新创建的线程数据<=最大线程数目)。

③keepAliveTime:when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.(超过核心线程数的线程,在新任务到来之前能存活的最长时间,如果没等到,那么它就拜拜了)

④unit: the time unit for the keepAliveTime argument.(就是keepAliveTime 参数的单位)

⑤BlockingQueue<Runnable> workQueue:the queue to use for holding tasks before they are executed. This queue will hold only the <tt>Runnable</tt> tasks submitted by the <tt>execute</tt> method.(等待执行的任务队列,它的作用就是用来存放还没有被执行的任务。这个队列仅仅用来存放被execute方法提交的Runnable任务,不要翻译成工作队列,那是给自己找麻烦)

⑥threadFactory:the factory to use when the executor creates a new thread.(线程工厂,用来创建新线程的工厂,一般使用默认工厂--Executors.defaultThreadFactory(),它是Executors类中的一个静态内部类的方法,返回一个实体类DefaultThreadFactory)

⑦RejectedExecutionHandler handler: the handler to use when execution is blocked because the thread bounds and queue capacities are reached.(当任务队列中任务已经达到了等待执行任务的队列的大小[有界队列会出现]时,要采取什么样的处理(handler)方式,取名叫拒绝策略,就是我应该怎么抛弃你)

 

下一篇,我们详细介绍下BlockingQueue<Runnable> 常用的等待执行任务存放的队列和RejectedExecutionHandler常用的任务拒绝策略。 

 

 

 

 

 

  • Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
  • 大小: 180 KB
  • Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
  • 大小: 1.2 MB
  • Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
  • 大小: 74 KB
  • Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
  • 大小: 25.1 KB
  • Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
  • 大小: 46.2 KB
  • Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
  • 大小: 82.7 KB
  • Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
  • 大小: 30.5 KB
  • Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
  • 大小: 59.8 KB
  • Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
  • 大小: 9.5 KB
  • Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
  • 大小: 128 KB
  • Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
  • 大小: 113 KB
  • Java多线程高并发高级篇(一)--线程池核心详解
            
    
    博客分类: 线程池 线程池多线程线程 
  • 大小: 170.3 KB