线程池

作者: 蜗牛写java | 来源:发表于2019-04-14 22:25 被阅读0次

    背景

    为什么出现线程池?

    1. 目前计算机CPU均为多核处理器,如果串行执行,必然造成资源上的浪费;
    2. 每次创建线程的时候,和销毁线程的时候,都不是我们程序关心的过程,程序关心的只是执行
    3. 有些业务程序不一定要串行执行,实际上可以并行去执行的;以节约相应时间
    4. 多个线程执行业务,那么怎么管理这些线程呢,是否可以统一管理

    使用线程池的好处

    1. 充分利用CPU资源
    2. 提高相应时间
    3. 统一管理线程(比如线程优先级、监控等)

    线程池工作原理

    线程池,字面上理解肯定有一个池子,这个池子可以是集合或者队列等,java中使用的是队列;池子存在了,那么就需要工作者,就是真实的工作线程;真实的工作线程控制多少呢,真实的工作者的个数;这些都存在了,那么往池子中注入业务是否需要一个入口,java中就是submit

    现实中例子:线程池好比一间客服办公室;办公室为池子;办公室必须保证n个接线员以上,n为核心线程数,工位数为最大线程数;接线员为真实的工作线程;电话号码(如10086)位线程池作业提交入口;超出的n个电话业务而等待的电话咨询数,为等待队列;如果等待的人数超出能等待的范围,就添加接线员到新的工位上,接电话;

    线程池UML

    线程池采用模板模式

    线程池UML.png

    ThreadPoolExecutor原理图

    线程池原理.png
    1. 运行线程数小于 corePoolSize,则创建新的线程来执行(创建新的线程,需要获取全局锁,这时候,其它线程可能在创建或者销毁等)
    2. 如果运行线程数大于等于corePoolSize,则任何加入BlockingQueue
    3. 如果BlockingQueue已满,maximumPoolSize>corePoolSize,则创建新的线程来处理任务(创建线程需要获取全局锁)
    4. 如果队列满,且maximumPoolSize也满,则执行拒绝策略
    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory,
                                  RejectedExecutionHandler handler)
    
    • corePoolSize : 当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其它空闲的基本线程能够执行任务也会创建线程,一直到任务数>=核心线程数时就不再创建。有prestartAllCoreThread()方法,可以提前创建
    • workQueue:任务队列
      • ArrayBlockingQueue:基于数组实现
      • LinkedBlockingQueue:基于链表实现,吞吐量高于前者
      • SynchronousQueue:一个不存储元素的阻塞队列;没插入操作必须等另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量又高于前者
      • PriorityBlockingQueue:一个具有优先级的无限阻塞队列
    • maximumPoolSize:线程池最大数量;如果队列满了,并且已创建的线程数小于最大线程数,则线程池会创建新的 线程执行任务;如果使用了无界队列的话,这个参数就没有效果
    • threadFactory:设置创建线程的工厂(可以设置创建的线程名称)
    • RejectedExecutionHandler:拒绝策略;当线程池都满了,说明线程池处于饱和状态,那么必须采用一种策略处理新提交的任务。
      • AbortPolicy:直接抛出异常(默认)
      • CallerRunsPolicy:只用调用者所在的线程来运行任务
      • DiscardOldestPolicy:丢弃队列中最近的一个任务,并执行当前任务
      • DiscardPolicy:不处理,直接丢弃掉
    • keepAliveTime:线程池的工作线程空闲后,保存时间
    • TimeUnit:保存时间单位

    线程池提交任务

    两种方式:

    1. execute() :提交不需要返回值的任务
    2. submit():提交需要返回值的任务,返回类型为Future<Object>

    关闭线程池

    shutdown,shutdownNow两种方式。原理都是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,无法响应中断的任务可能永远无法终止。

    相关文章

      网友评论

          本文标题:线程池

          本文链接:https://www.haomeiwen.com/subject/apeewqtx.html