【线程池】

news2024/9/25 9:36:25

什么是线程池?

线程池是一个可以复用线程的技术。简单来说,线程池是一种基于池化技术的思想来管理线程的技术,旨在减少线程的创建和销毁次数,提高系统的响应速度和吞吐量。它预先创建了一定数量的线程,并将这些线程放入到一个池中(即线程池),当需要执行新的任务时,不是直接创建新的线程,而是从线程池中取出一个空闲的线程来执行该任务,执行完毕后线程并不被销毁,而是放回线程池中供后续任务再次使用。

不使用线程池的问题

  1. 开销大:如果用户每发起一个请求,后台都需要创建一个新线程来处理,那么每次创建新线程都会带来较大的开销,包括系统资源的分配、初始化等过程。这些开销在请求量较大时会非常显著,严重影响系统性能。

  2. 资源浪费:当任务执行完毕后,如果直接销毁线程,那么在下一个任务到来时又需要重新创建线程,这会造成资源的频繁分配和回收,不仅开销大,而且浪费了宝贵的系统资源。

  3. 系统不稳定:如果请求过多,系统可能会创建大量的线程来处理这些请求。然而,系统的线程资源是有限的,过多的线程会导致线程之间竞争系统资源,引发线程切换、上下文切换等开销,进而可能导致系统响应变慢甚至崩溃。

线程池的工作原理

  • 初始状态:线程池中有几个初始化的线程(数量等于核心线程数),这些线程都处于空闲状态,等待任务的到来。
  • 任务提交:当有任务提交给线程池时,如果有空闲的线程,则直接由该线程执行任务;如果没有空闲的线程且任务队列未满,则任务被放入任务队列中等待。
  • 线程执行:线程从任务队列中取出任务并执行,执行完毕后线程再次回到空闲状态等待新的任务。
  • 动态调整:随着任务的增加,如果任务队列满了且线程数还没有达到最大线程数,则线程池会创建新的线程来执行任务。反之,如果一段时间内没有新的任务提交,线程池中的线程数量会逐渐减少到核心线程数(这取决于配置的线程池类型和策略)。
  • 关闭状态:当线程池被关闭时,它不再接受新的任务,并且会等待所有已经提交的任务执行完成后才销毁线程和释放资源。

线程池的创建

 

方式一 

通过创建ThreadPoolExecutor实例来管理线程池,ThreadPoolExecutor类提供了多个构造函数,允许开发者详细地配置线程池的参数,以满足不同的并发执行需求。

主要参数

  • corePoolSize(核心线程数):线程池中核心线程的数量。即使这些线程处于空闲状态,它们也不会被销毁,除非设置了allowCoreThreadTimeOuttrue
  • maximumPoolSize(最大线程数):线程池中允许的最大线程数。当工作队列已满时,如果线程数小于最大线程数,则会创建新线程来处理任务。
  • keepAliveTime(线程空闲时间):当线程数大于核心线程数时,这是多余空闲线程在终止前等待新任务的最长时间。
  • unit(时间单位):keepAliveTime参数的时间单位,如TimeUnit.SECONDS
  • workQueue(工作队列):用于保存等待执行的任务的阻塞队列。
  • threadFactory(线程工厂):用于创建新线程的工厂。如果不指定,则使用Executors.defaultThreadFactory()来创建线程。这个固定的代码记住就行了。
  • handler(拒绝处理策略):当任务队列和线程池都满了时,用于处理新任务的拒绝策略。
重点参数详解 

任务队列的实现

ThreadPoolExecutor的构造函数允许你指定一个BlockingQueue<Runnable>类型的任务队列。BlockingQueue是一个支持两个附加操作的队列,这两个操作是:在元素可用之前阻塞的检索操作,以及在没有额外空间时阻塞的插入操作。BlockingQueue接口有多种实现,每种实现都有其特定的用途和性能特性。

常见的BlockingQueue实现包括:

  1. ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。此队列按照先进先出(FIFO)的原则对元素进行排序。

  2. LinkedBlockingQueue:一个由链表结构组成的可选有界阻塞队列。如果创建时没有指定容量,则默认为Integer.MAX_VALUE,即无界队列。

  3. SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,反之亦然。

  4. PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。

如何选择任务队列

  • 如果你需要限制线程池中任务的数量,可以使用有界的ArrayBlockingQueueLinkedBlockingQueue
  • 如果你想要线程池在提交新任务时立即创建新线程(只要不超过maximumPoolSize),可以使用SynchronousQueue。但是,请注意,这可能会导致线程频繁地创建和销毁,从而增加开销。
  • 如果你需要按照任务的优先级来执行,可以使用PriorityBlockingQueue
线程池的注意事项 

线程池处理Runnable任务
package demo12;
//任务类
public class MyRunnable implements Runnable{
    @Override
    public void run() {
        //描述你的任务
        System.out.println(Thread.currentThread().getName()+"-->666");
        try {//为了方便观察,我们写一个延迟。
            Thread.sleep(Integer.MAX_VALUE);//Alt键加回车键捕捉一下
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
import java.util.concurrent.*;

public class ThreadPool {
    public static void main(String[] args) {
        //担心忘了,你可以按着ctrl键,然后点击就能看到它的那个提示
//            public ThreadPoolExecutor(int corePoolSize,
//        int maximumPoolSize,
//        long keepAliveTime,
//        TimeUnit unit,
//        BlockingQueue<Runnable> workQueue,
//        ThreadFactory threadFactory,
//        RejectedExecutionHandler handler) {
        ExecutorService pool=//多态写法
                //下面就创建好了一个线程池对象
                new ThreadPoolExecutor(3,5,8,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(4),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        Runnable target=new MyRunnable();
        //怎么把这个任务对象交给现场时来处理呢
        pool.execute(target);//线程池会自动创建一个新线程,自动处理这个任务,自动执行的。
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);//三个核心线程已经有了,此时复用前面的的核心线程。
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        //到了临时线程的创建时机了
        pool.execute(target);
        pool.execute(target);
        //三个任务在核心线程执行,四个任务在队列里面排着。两个任务在临时线程执行。
        //到了新任务拒绝的时候了
        pool.execute(target);
    }
}

 

 

线程池处理Callable任务

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

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

相关文章

MySQL高可用性实践指南

一 、Mysql 在服务器中的部署方法 1、安装依赖性 yum install libtirpc-devel-0.2.4-0.16.el7.x86_64.rpm -y yum install ncurses-devel.x86_64 -y yum install gcc-c -y yum install openssl-devel -y yum install cmake -y 2、下载并解压源码包 tar zxf mysql-boost-5.7…

十年热爱,小鹏汽车开启AI新篇章

“每一台小鹏汽车&#xff0c;都是同级别智能的天花板。”在8月27日的小鹏10年热爱之夜暨小鹏MONA M03上市发布会上&#xff0c;小鹏汽车董事长、CEO何小鹏不无自豪地表示。 对于小鹏汽车来说&#xff0c;此次发布会有着非凡的意义&#xff0c;因为它不仅是对小鹏汽车过去十年辉…

前端用js发送邮箱 前端发送邮箱

前端发送邮箱 安装包依赖邮箱授权码demo eg:picture页面发送内容有效接受效果 code参考别人写的code 说明 安装包依赖 yarn add nodemailernodemailer官网 邮箱授权码 邮箱授权码: 邮箱授权码需要开通&#xff0c;以QQ邮箱为例&#xff0c;其它大同小异 demo eg: picture…

ROCm Code Object Tooling

ROCm&#xff08;Radeon Open Compute&#xff09;提供了一系列的工具&#xff0c;用于检查和提取编译器生成的代码对象&#xff0c;包括可执行文件、目标文件和共享对象库。 一、roc-obj roc-obj 是 ROCm&#xff08;Radeon Open Compute&#xff09;提供的一个高层级工具&a…

【软件文档】需求规格说明书编制模板

1 范围 1.1 系统概述 1.2 文档概述 1.3 术语及缩略语 2 引用文档 3 需求 3.1 要求的状态和方式 3.2 系统能力需求 3.3 系统外部接口需求 3.3.1 管理接口 3.3.2 业务接口 3.4 系统内部接口需求 3.5 系统内部数据需求 3.6 适应性需求 3.7 安全性需求 3.8 保密性需求 3.9 环境需求…

数据结构(邓俊辉)学习笔记】串 14——BM_GS算法:构造gs表

以下&#xff0c;就来简要地介绍 gs 表的具体构造算法。算法为了便于理解其原理&#xff0c;这里将整个算法划分为若干的层次&#xff0c;并逐层递进、逐层细化。 我们首先需要引入 MS 子串与 ss 表的概念。实际上&#xff0c;相对于模式串中的任何一个字符 P[j] &#xff0c…

RP2040 C SDK开发串口的使用

RP2040 C SDK开发串口的使用 &#x1f4cd;环境搭建部署篇《RP2040 VSCode C/C开发环境快速部署》&#x1f516;RP2040 有硬件串口资源有2个。&#x1f33f;参考RP2040 C SDK Hardware APIS&#xff1a;https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#grou…

安卓APK重签名并查看MD5值-2024最新版

重签名 命令行运行&#xff1a; apksigner sign --ks your_keystore.jks --out output.apk input.apk在这个命令中&#xff1a; –ks 或 --keystore 参数后面是你的keystore文件路径。 your_keystore.jks 是你的keystore文件。 –out 参数后面是输出的签名后的APK文件名。 out…

发布npm包到GitLab教程

之前在研究如何搭建UI组件库&#xff08;内部使用&#xff09;&#xff0c;其中重要的一步就是发布npm包到GitLab。中间踩了很多坑&#xff0c;在这里记录一下整个流程方便大家快速上手。不足之处欢迎指出&#x1f64f; 1. 获取Token 在gitlab中打开access tokens申请页面&am…

鲲鹏服务器之ARM探知

什么叫arm架构 ARM架构过去称作进阶精简指令集机器&#xff08;Advanced RISC Machine&#xff0c;更早称作&#xff1a;Acorn RISC Machine&#xff09;&#xff0c;是一个32位精简指令集&#xff08;RISC&#xff09;处理器架构&#xff0c;其广泛地使用在许多嵌入式系统设计…

CSS系列之详解overflow(四)

一、什么是溢出 CSS 的 overflow 属性用于控制元素内容溢出时的表现方式。当元素的内容超出其指定的尺寸范围时&#xff0c;就会出现溢出现象。比如&#xff0c;一个元素的高度设置是 80px&#xff0c;但内容高度不只是 80px&#xff0c;内容此时就叫做溢出了。 那需要注意的…

【QT学习】1-2 Liunx环境下QT5.12.9软件安装1——VMware17.0.0虚拟机安装

注意&#xff1a;如果电脑已经安装低版本的VMware&#xff0c;千万不要卸载&#xff0c;直接覆盖安装&#xff0c;更新到新的安装版本 1.点击.exe文件&#xff0c;右键以管理员身份运行&#xff0c;点击下一步&#xff0c;下一步 2.选择软件安装位置后&#xff0c;点击下一步。…

Datawhale X 李宏毅苹果书 AI夏令营(深度学习进阶)task3

批量归一化 其实归一化简单一点理解就类似于我们学过的数学中的每个数值减去平均值除以标准差。 神经网络中的批量归一化&#xff08;Batch Normalization&#xff0c;BN&#xff09;就是其中一个“把山铲平”的想法。不要小看优化这个问题&#xff0c;有时候就算误差表面是凸…

面试基本内容

1.类加载器 类加载器加载过程: 加载:&#xff08;将字节码文件加载到运行时数据区的方法区中/元空间&#xff09; 链接:&#xff08;验证:检查字节码文件是否合法—>准备:静态类变量赋值为默认值&#xff0c;不会实例变量分配初始化—>解析:将常量池引用&#xff0c;转化…

Java | Leetcode Java题解之第382题链表随机节点

题目&#xff1a; 题解&#xff1a; class Solution {ListNode head;Random random;public Solution(ListNode head) {this.head head;random new Random();}public int getRandom() {int i 1, ans 0;for (ListNode node head; node ! null; node node.next) {if (rando…

14.神经网络的基本骨架 - nn.Module 的使用

神经网络的基本骨架 - nn.Module 的使用 Pytorch官网左侧&#xff1a;Python API&#xff08;相当于package&#xff0c;提供了一些不同的工具&#xff09; 关于神经网络的工具主要在torch.nn里 网站地址&#xff1a;torch.nn — PyTorch 1.8.1 documentation Containers C…

【Linux】CodeServer:云IDE部署

Code-server 是一个开源项目&#xff0c;它允许你在任何地方通过浏览器访问 Visual Studio Code&#xff08;VS Code&#xff09;编辑器。这意味着你可以在远程服务器或云端运行 VS Code&#xff0c;并通过浏览器进行编码、调试和开发&#xff0c;而不需要在本地安装 VS Code。…

EtherCAT 转 ModbusTCP 网关

设备简介 本产品是 EtherCAT 和 Modbus TCP 网关&#xff0c;使用数据映射方式工作。 本产品在 EtherCAT 侧作为 EtherCAT 从站&#xff0c;接 TwinCAT 、 CodeSYS 、 PLC等&#xff1b;在 ModbusTCP 侧做为 ModbusTCP 主站&#xff08; Client &#xff09;或从站…

<数据集>无人机识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;9229张 标注数量(xml文件个数)&#xff1a;9229 标注数量(txt文件个数)&#xff1a;9229 标注类别数&#xff1a;1 标注类别名称&#xff1a;[UAV] 使用标注工具&#xff1a;labelImg 标注规则&#xff1a;对类别…

我如何解决 java.lang.ClassNotFoundException:javax.xml.bind.DatatypeConverter

优质博文&#xff1a;IT-BLOG-CN 问题 我如何解决java.lang.ClassNotFoundException&#xff1a;javax.xml.bind.DatatypeConverter 2024-08-25T02:31:25.46202:00 ERROR 21868 --- [fintonic-oauth] [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet…