• 自己动手写线程池——向JDK线程池进发


    🚀 优质资源分享 🚀

    学习路线指引(点击解锁) 知识定位 人群定位
    🧡 Python实战微信订餐小程序 🧡 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
    💛Python量化交易实战💛 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

    自己动手写线程池——向JDK线程池进发

    前言

    在前面的文章自己动手写乞丐版线程池中,我们写了一个非常简单的线程池实现,这个只是一个非常简单的实现,在本篇文章当中我们将要实现一个和JDK内部实现的线程池非常相似的线程池。

    JDK线程池一瞥

    我们首先看一个JDK给我们提供的线程池ThreadPoolExecutor的构造函数的参数:

    
    
    |  | public ThreadPoolExecutor(int corePoolSize, |
    |  |  int maximumPoolSize, |
    |  |  long keepAliveTime, |
    |  |  TimeUnit unit, |
    |  |  BlockingQueue workQueue, |
    |  |  ThreadFactory threadFactory, |
    |  |  RejectedExecutionHandler handler) |
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    参数解释:

    • corePoolSize:这个参数你可以理解为线程池当中至少需要 corePoolSize 个线程,初始时线程池当中线程的个数为0,当线程池当中线程的个数小于 corePoolSize 每次提交一个任务都会创建一个线程,并且先执行这个提交的任务,然后再去任务队列里面去获取新的任务,然后再执行。
    • maximumPoolSize:这个参数指的是线程池当中能够允许的最大的线程的数目,当任务队列满了之后如果这个时候有新的任务想要加入队列当中,当发现队列满了之后就创建新的线程去执行任务,但是需要满足最大的线程的个数不能够超过 maximumPoolSize 。
    • keepAliveTime 和 unit:这个主要是用于时间的表示,当队列当中多长时间没有数据的时候线程自己退出,前面谈到了线程池当中任务过多的时候会超过 corePoolSize ,当线程池闲下来的时候这些多余的线程就可以退出了。
    • workQueue:这个就是用于保存任务的阻塞队列。
    • threadFactory:这个参数倒不是很重要,线程工厂。
    • handler:这个表示拒绝策略,JDK给我们提供了四种策略:
      • AbortPolicy:抛出异常。
      • DiscardPolicy:放弃这个任务。
      • CallerRunPolicy:提交任务的线程执行。
      • DiscardOldestPolicy:放弃等待时间最长的任务。

    如果上面的参数你不能够理解,可以先阅读这篇文章自己动手写乞丐版线程池。基于上面谈到的参数,线程池当中提交任务的流程大致如下图所示:

    自己动手实现线程池

    根据前面的参数分析我们自己实现的线程池需要实现一下功能:

    • 能够提交Runnable的任务和Callable的任务。
    • 线程池能够自己实现动态的扩容和所容,动态调整线程池当中线程的数目,当任务多的时候能够增加线程的数目,当任务少的时候多出来的线程能够自动退出。
    • 有自己的拒绝策略,当任务队列满了,线程数也达到最大的时候,需要拒绝提交的任务。

    线程池参数介绍

    
    
    |  | private AtomicInteger ct = new AtomicInteger(0); // 当前在执行任务的线程个数 |
    |  | private int corePoolSize; |
    |  | private int maximumPoolSize; |
    |  | private long keepAliveTime; |
    |  | private TimeUnit unit; |
    |  | private BlockingQueue taskQueue; |
    |  | private RejectPolicy policy; |
    |  |  |
    |  | private ArrayList workers = new ArrayList<>(); |
    |  |  |
    |  | private volatile boolean isStopped; |
    |  | private boolean useTimed; |
    |  |  |
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    参数解释如下:

    • ct:表示当前线程池当中线程的个数。
    • corePoolSize:线程池当中核心线程的个数,意义和上面谈到的JDK的线程池意义一致。
    • maximumPoolSize:线程池当中最大的线程个数,意义和上面谈到的JDK的线程池意义一致。
    • keepAliveTime 和 unit:和JDK线程池的参数意义一致。
    • taskQueue:任务队列,用不保存提交的任务。
    • policy:拒绝策略,主要有一下四种策略:
    
    
    |  | public enum RejectPolicy { |
    |  |  |
    |  |  ABORT, |
    |  |  CALLER\_RUN, |
    |  |  DISCARD\_OLDEST,
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    如何快速优化几千万数据量的订单表
    【JAVASE系列】06_继承,多态与final
    最新AI系统+ChatGPT网站H5源码+AI绘画系统,DALL-E3文生图,详细图文搭建教程/文档分析/识图理解
    知识图谱-KGE(Knowledge Graph Embedding):概述【将知识图谱中的实体、关系进行Embedding表示】
    rsync 远程同步
    Tableau表格取消合并单元格
    如何用AR Engine开发一个虚拟形象表情包?
    【C++】—— 模板进阶
    大厂面试解码:如何准备Google, Amazon等公司的面试
    Android 11 getPackageManager().getPackageInfo 返回null
  • 原文地址:https://blog.csdn.net/qq_43479892/article/details/127456475