1、使用线程池的好处?

在实际使用中,线程是很占用系统资源的,如果对线程管理不完善的话很容易导致系统问题。因此,在大多数并发框架中都会使用线程池来管理线程,使用线程池管理线程主要有如下好处:

1、使用线程池可以重复利用已有的线程继续执行任务,避免线程在创建销毁时造成的消耗

2、由于没有线程创建和销毁时的消耗,可以提高系统响应速度

3、通过线程可以对线程进行合理的管理,根据系统的承受能力调整可运行线程数量的大小等

2、线程池分类?

image.png
1. newCachedThreadPool:创建一个可进行缓存重复利用的线程池

  1. newFixedThreadPool:创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程,线程池中的线程处于一定的量,可以很好的控制线程的并发量

  2. newSingleThreadExecutor:创建一个使用单个 worker 线程的Executor ,以无界队列方式来运行该线程。线程池中最多执行一个线程,之后提交的线程将会排在队列中以此执行

4. newSingleThreadScheduledExecutor:创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期执行

5. newScheduledThreadPool:创建一个线程池,它可安排在给定延迟后运行命令或者定期的执行

6. newWorkStealingPool:创建一个带并行级别的线程池,并行级别决定了同一时刻最多有多少个线程在执行,如不传并行级别参数,将默认为当前系统的CPU个数

3、线程池的核心参数

  1. corePoolSize:核心线程数
  2. maximumPoolSize: 线程池最大线程数
  3. keepAliveTime: 空闲线程存活时间
  4. unti:时间单位
  5. workQueue:阻塞队列,用于保存任务的阻塞队列
  6. threadFactory:创建线程的工程类
  7. handler:饱和策略(拒绝策略)

    4、线程池执行流程

    image.png
    当一个任务提交至线程池之后,
    1.线程池首先判断核心线程池里的线程是否已经满了。如果不是,则创建一个新的工作线程来执行任务。否则进入2
    2.判断工作队列是否已经满了,倘若还没有满,将线程放入工作队列。否则进入3.
    3. 判断线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行。如果线程池满了,则交给饱和策略来处理任务。

    5、拒绝策略

    ThreadPoolExecutor.AbortPolicy(系统默认): 丢弃任务并抛出RejectedExecutionException异常,让你感知到任务被拒绝了,我们可以根据业务逻辑选择重试或者放弃提交等策略
    ThreadPoolExecutor.DiscardPolicy: 也是丢弃任务,但是不抛出异常,相对而言存在一定的风险,因为我们提交的时候根本不知道这个任务会被丢弃,可能造成数据丢失。
    ThreadPoolExecutor.DiscardOldestPolicy: 丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程),通常是存活时间最长的任务,它也存在一定的数据丢失风险
    ThreadPoolExecutor.CallerRunsPolicy:既不抛弃任务也不抛出异常,而是将某些任务回退到调用者,让调用者去执行它。

    6、线程池关闭

    关闭线程池,可以通过shutdown和shutdownNow两个方法
    原理:遍历线程池中的所有线程,然后依次中断
    1、shutdownNow首先将线程池的状态设置为STOP,然后尝试停止所有的正在执行和未执行任务的线程,并返回等待执行任务的列表;
    2、shutdown只是将线程池的状态设置为SHUTDOWN状态,然后中断所有没有正在执行任务的线程