当前位置 博文首页 > 文章内容

    David的博客:线程池及核心参数

    作者:21344 栏目:未分类 时间:2021-11-26 13:24:38

    1 为什么需要线程池

    一般来说,线程的生命周期需要通过 new(新建)->start(就绪)->running(运行中)->dead(消亡)
    假设每个状态到下一个状态需要的时间是
    1,2,3 秒
    但是我们往往只是关心running 那个状态就可以了,这是线程需要执行的任务
    使用线程池,创建一定数量的线程,专门执行任务的run 方法,实现了线程的复用,同时也减少了其他状态的占比,提高了整个系统的运行效率

    2 线程池的核心参数

    核心线程,最大线程,定义不好解释,还是看这两个参数在执行任务的过程中对worker 线程的创建的影响吧。
    这两个参数的目的是:

    1. 尽量少的创建线程(核心线程是初始化线程池时创建的,当有任务来时,核心线程都忙,则往队列放,而不是立刻创建线程)
    2. 尽量快的执行任务(优先使用核心线程执行任务,不够,再入队,队满,使用新线程执行)
    3. 控制最大线程数(资源的限制)
      记忆:任务到来,优先使用核心线程,核心线程数不够,再排队,队列排满再开启新线程执行任务,核心线程+非核心线程数达到最大线程数,则将任务交给拒绝策略处理。
      在这里插入图片描述

    3 线程池的分类

    FixedExcutor:固定线程池大小
    SingleThreadPool:单线程,
    CachedThreadPool:可缓存

        Executors.newCachedThreadPool();
        Executors.newSingleThreadExecutor();//单线程线程池
        Executors.newFixedThreadPool(2);//固定线程池大小
    

    4 线程池的底层实现

    1. 使用阻塞队列去放置未被执行的任务
    2. worker 线程则是在执行完当前任务后,从队列中取出任务执行

    核心构造方法:

    ThreadPoolExecutor(int corePoolSize,// 核心线程数
                                  int maximumPoolSize,// 最大线程数
                                  long keepAliveTime,// 线程闲闲置存活时间,如果闲置时间超过改时间,则回收该线程(长时间没任务)
                                  TimeUnit unit,// 时间单位
                                  BlockingQueue<Runnable> workQueue)//任务队列
    

    5阻塞队列的常用方法;

    1. add/offer 入队,前者队列满时,会抛出异常,后者会返回false,offer 还可以设置时间参数,限时入队
    2. peek/pool 返回队头元素,前者返回,但是不移除,后者返回且移除
    3. 读写锁的使用 (ReentrantLock)takeLock,putLock

    6 线程池的好处

    1. 响应快:系统启动就创建一部分线程
    2. 降低资源消耗:重复利用机制,减少线程重复创建销毁造成的损耗
    3. 提高线程可管理性:统一分配,调优和监控
    cs