一文带你深入了解线程池

news2025/1/16 18:02:50

目录

    • 一. 什么是线程池
    • 二. 为什么要使用线程池
    • 三. 线程池的参数
    • 四. 线程池的工作流程
    • 五. 使用Executors 创建常见的功能线程池


一. 什么是线程池

简单来说,线程池就是提前创建好一批线程,当有任务的时候,从池子中取出一个线程去执行该任务,执行结束后,再把线程放回池子中,以备循环使用。

二. 为什么要使用线程池

  1. 降低资源消耗,线程一个生命周期需要经过创建、调度、销毁过程,使用线程池,可以降低线程创建和销毁的消耗。
  2. 提高响应速度,当有任务分配过来时,可以直接调度,不需要创建线程,速度快。
  3. 提高可管理性,使用线程池可以对线程进行统一的分配、调优和监管。

三. 线程池的参数

以标准库的线程池为例,它的参数列表如下:

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

下面对这些参数进行介绍:

corePoolSize:核心线程数,即常备线程数

maximumPoolSize:最大线程数,常备线程数 + 临时线程数

keepAliveTime:线程的空闲时间,简单来说,就是临时线程活干完的时候,不会直接销毁临时线程,而是会观察一段时间,如果没有其他任务,再进行销毁。

TimeUnit unit:时间单位,m、ms等。

workQueue:工作队列,没有临时线程时,任务太多,核心线程(常备线程)做不完,则把任务存储到工作队列中。

threadFactory:线程工厂,用来创建线程,一般使用默认的线程工厂就可以了。

handler:拒绝策略,任务太多了,工作队列满了,就会执行拒绝策略。

常见的拒绝策略:

在这里插入图片描述

ThreadPoolExecutor.AbortPolicy:拒绝任务,抛出异常(直接拒绝,和领导吵一架)。

ThreadPoolExecutor.CallerRunsPolicy:由调用者来执行该任务(拒绝任务,让领导去做)。

ThreadPoolExecutor.DiscardOldestPolicy:把新任务加入,丢弃最早的任务。

ThreadPoolExecutor.DiscardPolicy:直接拒绝,什么也不做。

四. 线程池的工作流程

  1. 线程池刚创建时,线程池是一个空的,没有任何线程。
  2. 随着任务的提交,线程池开始创建线程:
    a. if (当前线程数 < corePoolSize) ,创建线程
    b. if (当前线程数 == corePoolSize) ,则把任务添加到工作队列中去
    c. 队列满了,if (当前线程数 < maximumPoolSize) ,创建线程(此时创建的为临时线程)
    d. 队列满了,if (当前线程数 == maximumPoolSize) ,执行拒绝策略
  3. 随着任务的执行,任务逐渐减少,线程有了空闲时间,则:
    if(空闲时间 > keepAliveTime && 当前线程数 > corePoolSize),则销毁线程,直到 当前线程数 == corePoolSize。

五. 使用Executors 创建常见的功能线程池

Executors为我们封装好了 4 种常见的功能线程池如下:

  1. 定长线程:FixedThreadPool
  2. 定时线程:ScheduledThreadPool
  3. 可缓存线程池:CachedThreadPool
  4. 单线程化线程池:SingleThreadExecutor

使用 Executors.newFixedThreadPool(10) 能创建出固定包含 10 个线程的线程池,该方法创建的线程池的返回值类型均为 ExecutorService。

定长线程:FixedThreadPool
源码:

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

    public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }

特点:定长线程池 核心线程数 == 最大线程数 ,即没有临时线程,且执行完毕会立刻回收,这种类型的线程池使用频率最高。

定时线程:ScheduledThreadPool
源码:

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

    public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }
  **加粗样式** **加粗样式** public ScheduledThreadPoolExecutor(int corePoolSize,
                                       ThreadFactory threadFactory) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue(), threadFactory);
    }

特点:定时线程池的核心线程数量固定,虽然它的构造方法里面没有写最大线程的数量是多少,但是跟进查看源码可以知道,最大线程数量是等于 Integer.MAX_VALUE 的,工作队列是高度定制化的延迟阻塞队列DelayedWorkQueue,其实现原理和DelayQueue基本一样,核心数据结构是二叉最小堆的优先队列,队列满时会自动扩容,所以offer操作永远不会阻塞,maximumPoolSize也就用不上了,所以线程池中永远会保持至多有corePoolSize个工作线程正在运行。

可缓存线程池:CachedThreadPool
源码:

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

    public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>(),
                                      threadFactory);
    }

特点:可缓存线程池的核心线程数 = 0,最大线程数为 Integer.MAX_VALUE ,它会在执行闲置60s后回收,任务队列为不储存元素的阻塞队列。适合于并发不固定的短期的小任务。

单线程化线程池:SingleThreadExecutor
源码:

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

    public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }

特点:单线程化线程池的核心线程数 == 最大线程数 == 1,执行完毕会立即回收,任务队列为链表结构的有界队列。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/158887.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

再说多线程(二)——细说Monitor类

在上一节我们已经讨论了使用Lock来保证并发程序的一致性&#xff0c;Lock锁是借助了Monitor类的功能。本节将详细的介绍Monitor类&#xff0c;以及如何通过Monitor类的成员函数实现并行程序的一致性。1.Monitor类介绍根据微软的说法&#xff0c;C#中的监视器类提供了一种同步对…

Microsoft Visual SourceSafe的使用

1、介绍 Microsoft Visual SourceSafe&#xff0c;简称vss。是一款早期微软推出的版本管理工具。跟据官方的定义&#xff0c;vss有两种控制模式&#xff1a;独占&#xff08;Lock-Modify-Unlock Model&#xff09;和并行&#xff08;Copy-Modify-Merge Model&#xff09;。独占…

程序的安装——软件安装包的制作、软件源的使用

读书笔记 —— 《嵌入式C语言自我修养》 软件安装 linux 安装包的制作 编译 软件安装包路径 使用dpkg命令来制作安装包 及 安装包的卸载 软件仓库 更新源 查看具体需要更新的软件包 更新软件包 软件安装 软件安装的过程其实就是将一个可执行文件安装到ROM的过…

安全狗云原生安全从1.X到2.X的演变之路(1)

随着云计算技术的蓬勃发展&#xff0c;传统上云实践中的应用升级缓慢、架构臃肿、无法快速迭代等“痛点”日益明显。能够有效解决这些“痛点”的云原生技术正蓬勃发展&#xff0c;成为赋能业务创新的重要推动力&#xff0c;并已经应用到企业核心业务。然而&#xff0c;云原生技…

大型数据中心分层分布式谐波治理方案设计与效果分析

摘要&#xff1a;数据中心行业在国民经济中起到了不可替代的作用,但其繁多的非线性电力负载,如通讯系统、大型计算机、网络控制设备、变频空调、各种数码办公设备、灯光调控系统、UPS、监控系统等给其供电系统带来了严重的谐波干扰,对大型数据中心的运行安全造成了较大的威胁,为…

200:vue+openlayers 添加删除多边形,modify feature,双向互动颜色显示

第200个 点击查看专栏目录 本示例的目的是介绍如何在vue+openlayers项目中添加删除多边形,每绘制一个,左侧列表出一个信息。 hover左侧文字,右边地图上红色显示图形,点击选中右侧地图上某feature,变成蓝色高亮,同时左侧也会蓝色显示,做到双向互动。 高亮显示某feature,…

如何删除图片数据中的重复数据

我们在工作中经常这种情况&#xff0c;leader给你一堆数据&#xff0c;让你用这些没有清洗过的数据完成项目。痛苦的是&#xff0c;这批数据居然存在很多重复的样本。那如何删除这些冗余数据呢&#xff1f;imagehash库非常好用。 github地址&#xff1a;https://github.com/ch…

络达开发----如何开启DMIC

芯片型号&#xff1a;AB1565 功能模块&#xff1a;数字MIC接口的使用 AB1656评估板上支持两路数字MIC&#xff0c;分别为DMIC0和DMIC1&#xff0c;如果图1所示&#xff0c;分别 可以由GPIO_2/3/4/5/13/14/15/16来当数字MIC的接口。 图1&#xff1a;支持DMIC的IO口但是评估板上…

MAC M1使用Rosetta安装python3.6

在使用网上提到的brew和pyenv安装的时候&#xff0c;我的电脑总会报BUILD FAILED错误。 找了一天才找到解决办法&#xff0c;真的十分痛苦&#xff0c;特此记录一下&#xff0c;让别的小伙伴也不再迷茫。 解决办法参考网址&#xff1a;click here&#xff08;需要VPN&#xff…

html跑马灯走马灯效果

演示 <marquee width"100%" scrollamount"5"> <a href"http://www.taobaojp5.tk"><font face"楷体_GB2312" color"#ff0000" size"3"></font><strong>带有超链接的跑马灯!点我试试&…

uwsgi 快速入门

文章目录uwsgi 快速入门一、 概述1、 简单介绍2、 环境配置二、 第一个 WSGI 应用1、 运行2、 添加并发三、 结合 Web 服务器使用1、 Flask2、 Django3、 Nginx配置uwsgi 快速入门 一、 概述 1、 简单介绍 WSGI&#xff08;Web Server Gateway Interface&#xff09;&#x…

FPGA知识汇集-ASIC移植中的FPGA芯片划分

通常&#xff0c;FPGA单芯片难以容纳下整个ASIC设计&#xff0c;因此需要将整个系统划分到多颗FPGA芯片中运行&#xff08;见图1&#xff09;&#xff0c;工程师往往需要借助原型验证平台来实现这样的目标。多芯片的划分绝不是简单的将不同的模板放置到不同的FPGA中那么简单&am…

算法训练营 day16 二叉树 二叉树的最大深度 二叉树的最小深度 完全二叉树的节点个数

算法训练营 day16 二叉树 二叉树的最大深度 二叉树的最小深度 完全二叉树的节点个数 二叉树的最大深度 104. 二叉树的最大深度 - 力扣&#xff08;LeetCode&#xff09; 给定一个二叉树&#xff0c;找出其最大深度。 二叉树的深度为根节点到最远叶子节点的最长路径上的节点…

(JVM) 沙箱安全机制

沙箱安全机制 沙箱安全机制 保证程序安全 保护Java原生的JDK代码 Java安全模型的核心就是Java沙箱&#xff08;sandbox&#xff09;。什么是沙箱&#xff1f;沙箱是一个限制程序运行的环境。 沙箱机制就是将Java代码限定在虚拟机&#xff08;JVM&#xff09;特定的运行范围…

Javaweb+Vue开发中常见的问题-1

1.Vue乱码问题 Vue2 修改打包文件的编码格式&#xff08;webpack-encoding-plugin&#xff09;_一碗单炒饭的博客-CSDN博客_vue如何设置打包文件的编码格式 怎么把命令行改成utf_8 - 沿途百知 设置命令行的编码格式&#xff1a;chcp 65001 https://bbs.csdn.net/topics/3935426…

基于微信小程序云开发的职业学校招生报名小程序源码,职业学校招生报名微信小程序源码 ,职业学校招生报名小程序源码

功能介绍 这是一个以报名为核心的职业学校招生小程序&#xff0c;目的是方便想要系统学习技能&#xff0c;入门某项技能或者领域的初高中毕业生&#xff0c;了解该学校的基本情况及各个专业&#xff0c;并提供报名路径&#xff0c;致力于技能型人才培养。本程序前后端代码完整…

ikun运球新姿势-- 反弹shell

目录 反弹Shell 反弹shell的概述 正向连接 反向连接 为什么需要反弹shell 利用netcat反弹shell 利用Bash反弹shell curl配合Bash反弹shell 将反弹shell的命令写入定时任务 将反弹shell的命令写入/etc/profile文件 python脚本反弹shell 反弹Shell 反弹shell的概述 …

免费的移动硬盘数据恢复软件EasyRcovery15

在日常工作中&#xff0c;移动硬盘可以帮助用户存储重要的文件资料&#xff0c;作为可移动的存储设备&#xff0c;在外出工作时携带起来也比较的方便&#xff0c;而且它的存储空间大&#xff0c;不会出现数据文件过大而无法储存的情况。今天小编就来和大家分享一下&#xff0c;…

算能杯|全国大学生集成电路创新创业大赛开启报名!

第七届全国大学生集成电路创新创业大赛正式开幕&#xff0c;“算能杯”主题是基于TPU芯片的边缘计算系统设计&#xff0c;算能为参赛选手提供了超强算力的开发板、无人机、人工智能小车等硬件资源&#xff0c;欢迎各大高校的开发者报名参与&#xff01; 近几年&#xff0c;边缘…

4-选择题练手

1.在Java中&#xff0c;以下关于方法重载和方法重写描述正确的是A. 方法重载和方法的重写实现的功能相同 B. 方法重载出现在父子关系中&#xff0c;方法重写是在同一类中 C. 方法重载的返回值类型必须一致&#xff0c;参数项必须不同D.方法重写的返回值类型必须相同或相容答&am…