• 浅析线程池


    众所周知,频繁地创建和销毁线程对于CPU来说,压力是很大的,而线程池通过复用线程,就可以避免线程频繁地创建和销毁。

    1.线程池分类

    Java 的 Executors 工具类中提供了 5 种类型的线程池创建方法,来看下它们的特点和适用场景。

    newFixedThreadPool

    固定大小线程池,特点是线程数固定,使用无界队列,适用于任务数量不均匀的场景、对内存压力不敏感但系统负载比较敏感的场景;

    newCachedThreadPool

    Cached 线程池,特点是不限制线程数,适用于要求低延迟的短期任务场景;

    newSingleThreadExecutor

    单线程线程池,就是一个线程的固定线程池,适用于需要异步执行但需要保证任务顺序的场景;

    newScheduledThreadPool

    Scheduled 线程池,适用于定期执行任务场景,支持按固定频率定期执行和按固定延时定期执行两种方式;

    newWorkStealingPool

    工作窃取线程池,使用的是 ForkJoinPool,是固定并行度的多任务队列,适合任务执行时长不均匀的场景。

    2.线程池参数

    线程池除了工作窃取线程池外,都是通过 ThreadPoolExecutor 的不同初始化参数来创建的。阿里巴巴规范不推荐我们直接使用Executors类直接进行创建线程池,为的是我们能更好的掌握线程池的使用
    在这里插入图片描述
    corePoolSize:核心线程数,默认情况下核心线程会一直存活
    maximumPoolSize:最大线程数,决定线程池最多可以创建的多少线程
    keepAliveTime:设置线程空闲时间,
    unit:空闲时间的单位,
    workQueue:缓冲队列,ArrayBlockingQueue 是一个有界队列,就是指队列有最大容量限制;LinkedBlockingQueue 是无界队列,就是队列不限制容量;SynchronousQueue,是一个同步队列,内部没有缓冲区。
    threadFactory:线程池工厂方法,线程工厂用来创建新线程,可以用来对线程的一些属性进行定制,例如线程的 group、线程名、优先级等。一般使用默认工厂类即可
    handler:线程池满时的拒绝策略。Abort 策略在线程池满后,提交新任务时会抛出 RejectedExecutionException,这个也是默认的拒绝策略。Discard 策略会在提交失败时对任务直接进行丢弃。CallerRuns 策略会在提交失败时,由提交任务的线程直接执行提交的任务。DiscardOldest 策略会丢弃最早提交的任务。

    3.线程池执行流程

    向线程提交任务时可以使用 execute 和 submit,区别就是 submit 可以返回一个 future 对象,通过 future 对象可以了解任务执行情况,可以取消任务的执行,还可获取执行结果或执行异常。submit 最终也是通过 execute 执行的。
    流程:

    1. 向线程池提交任务时,会首先判断线程池中的线程数是否大于设置的核心线程数,如果不大于,就创建一个核心线程来执行任务。

    2. 如果大于核心线程数,就会判断缓冲队列是否满了,如果没有满,则放入队列,等待线程空闲时执行任务。

    3. 如果队列已经满了,则判断是否达到了线程池设置的最大线程数,如果没有达到,就创建新线程来执行任务。

    4. 如果已经达到了最大线程数,则执行指定的拒绝策略。

    4. 已知线程池的创建

    1. newFixedThreadPool

    固定大小线程池创建时核心和最大线程数都设置成指定的线程数,这样线程池中就只会使用固定大小的线程数。

    2. newCachedThreadPool

    队列使用无界队列 LinkedBlockingQueue。

    3. newSingleThreadExecutor

    Single 线程池就是线程数设置为 1 的固定线程池。

    4. newScheduledThreadPool

    Cached 线程池的核心线程数设置为 0,最大线程数是 Integer.MAX_VALUE,主要是通过把缓冲队列设置成 SynchronousQueue,这样只要没有空闲线程就会新建。

    5. newWorkStealingPool

    Scheduled 线程池与前几种不同的是使用了 DelayedWorkQueue,这是一种按延迟时间获取任务的优先级队列。

  • 相关阅读:
    备忘录模式-撤销功能的实现
    单元测试用例到底该如何设计?
    Java系列 —— 注解
    大数据与智慧物流
    23种设计模式(四)单例模式(阁瑞钛伦特软件-九耶实训)
    解决JSON传参报错问题
    Docker 部署 Geoserver
    Hi3861 OpenHarmony嵌入式应用入门--轮询按键
    DTD和XSD的区别
    MySQL约束
  • 原文地址:https://blog.csdn.net/mr4569870/article/details/126407949