【线程池】

什么是线程池?

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

不使用线程池的问题

  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{@Overridepublic 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.mzph.cn/bicheng/52748.shtml

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

相关文章

Java中的定时器(Timer)

目录 一、什么是定时器? 二、标准库中的定时器 三、实现自定义定时器 一、什么是定时器? 定时器就像一个"闹钟"&#xff0c;当它到达设定的时间后&#xff0c;就会执行预定的代码。 例如&#xff0c;我们在TCP的超时重传机制中讲过&#xff0c;如果服务器在规定…

DNS劫持问题

目录 DNS劫持概述 定义 图示 ​编辑图示说明 DNS劫持的原理 1. DNS请求与响应过程 图示 ​编辑2. 劫持发生点 本地劫持 路由器劫持 中间人攻击 图示 ​编辑图示说明 DNS劫持的影响 1. 对个人用户的影响 图示 ​编辑图示说明 2. 对企业的影响 图示 ​编辑图示…

0828作业+梳理

一、作业 代码&#xff1a; #include <iostream>using namespace std;using datatype int; //类型重命名 #define MAX 2 //宏定义 //结构体定义 struct Sqlist { private:datatype *data; //顺序表数组int size 0; //数组大小int len 0; …

Ubuntu 16.04下Firefox版本更新

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; 在Ubuntu 16.04上更新Firefox的过程可能涉及多个步骤&#xff0c;具体取决于你的需求&#xff0c;比如是要安装一个稳定版本&#xff0c;还是需要使用最新的开发者版本或beta版本。下面我将详细介绍如何在Ub…

Python酷库之旅-第三方库Pandas(105)

目录 一、用法精讲 456、pandas.DataFrame.rdiv方法 456-1、语法 456-2、参数 456-3、功能 456-4、返回值 456-5、说明 456-6、用法 456-6-1、数据准备 456-6-2、代码示例 456-6-3、结果输出 457、pandas.DataFrame.rtruediv方法 457-1、语法 457-2、参数 457-3…

搭建面向切面编程项目

此项目在整合Mybatis基础上修改&#xff0c;可参考主页的整合Mybatis文章 注解版本 第一步 引入maven坐标 <!-- 切面编程所需jar包--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId>…

学生管理系统升级(登录注册 + 关联学生管理系统)

新增需求 这是在昨天的基础初代版本上面新增一个登录注册忘记密码的功能 需求分析 注册 登录 忘记密码 user类代码呈现 package StudentSystem;public class User {private String username;private String password;private String personID;private String phoneNumber;pu…

PHP同城派送多区域运营配送小程序源码

&#x1f69a;&#x1f4a8;「同城派送多区域运营小程序」——让每一份需求快速触达&#xff01;&#x1f308;&#x1f680; &#x1f525; 开篇燃爆&#xff1a;同城生活新风尚&#xff0c;一键速达不是梦&#xff01; Hey小伙伴们&#xff0c;你还在为找不到合适的同城服务…

推荐并整理一波vscode插件(哪些内置了,哪些好用)

文章目录 背景现在还在用的&#xff08;21款&#xff09;Chinese(Simplified)简体中文Chinese LoremLorem ipsumCode Runner&#xff08;很推荐&#xff09;Codeium: AI Coding Autocomplete&#xff08;推荐&#xff09;Draw.io IntegrationESLintHighlight Matching TagJavaS…

甄选范文“论软件系统建模方法及其应用”,软考高级论文,系统架构设计师论文

论文真题 软件系统建模(Software System Modeling)是软件开发中的重要环节,通过构建软件系统模型可以帮助系统开发人员理解系统、抽取业务过程和管理系统的复杂性,也可以方便各类人员之间的交流。软件系统建模是在系统需求分析和系统实现之间架起的一座桥梁,系统开发人员…

【二叉树】OJ题目

&#x1f31f;个人主页&#xff1a;落叶 目录 单值⼆叉树 【单值二叉树】代码 相同的树 【相同二叉树】代码 对称⼆叉树 【对称二叉树】代码 另一颗树的子树 【另一颗树的子树】代码 二叉树的前序遍历 【二叉树前序遍历】代码 二叉树的中序遍历 【二叉树中序遍历】…

NVIDIA将在Hot Chips 2024会议上展示Blackwell服务器装置

NVIDIA 将在 Hot Chips 2024 上展示其 Blackwell 技术堆栈&#xff0c;并在本周末和下周的主要活动中进行会前演示。对于 NVIDIA 发烧友来说&#xff0c;这是一个激动人心的时刻&#xff0c;他们将深入了解NVIDIA的一些最新技术。然而&#xff0c;Blackwell GPU 的潜在延迟可能…

【freeDiameter】服务端和客户端的连接流程

连接流程详解 进程启动时&#xff0c;先使用main_cmdline解析命令行参数&#xff0c;比如使用-c就会使用指定路径的配置文件&#xff0c;使用-d就会启用后台进程。 之后使用fd_core_initialize初始化核心库。具体会先使用fd_conf_init初始化配置&#xff0c;比如设置各项的默…

最长的一帧学习 part3

文章目录 八、osgUtil:: SceneView::cull ()part1 初始化必要的SceneView类成员变量part2 立体显示的处理part3 执行SceneView::cullStage函数&#xff0c;它也是场景视图筛选工作的核心函数part3.1 首先统计场景中的遮挡节点&#xff08;OccluderNode&#xff09;&#xff0c;…

缺失ffmpeg.dll要用什么修复方法?快速恢复丢失的ffmpeg.dll文件

多媒体软件用户常常会遭遇一个提示&#xff1a;系统无法找到ffmpeg.dll文件。这类情况经常在启动视频编辑软件、流媒体播放应用或其他音视频处理工具时出现&#xff0c;导致相关程序无法正确加载和执行。ffmpeg.dll是一种关键的动态链接库文件&#xff0c;负责处理复杂的视频和…

ssrf+redis未授权访问漏洞复现

ssrfredis未授权访问漏洞复现 一&#xff0c;pikachu靶场练习 docker拉取环境&#xff1a; docker run -d -p 8765:80 8023/pikachu-expect:latest国内很多加速源都用不成&#xff0c;配置代理拉取即可&#xff0c;配置方式如下&#xff1a; 1&#xff0c;新建目录 mkdir -…

数据结构与算法的代码实现(C++版)

数据结构与算法的代码实现&#xff08;C版&#xff09; 1. 线性表的顺序表示和实现1.1 线性表的初始化1.2 线性表的销毁1.3 线性表的清空1.4 线性表的长度1.5 判断线性表是否为空1.6 线性表的线性表取值1.7 线性表的顺序查找1.8 线性表的插入1.9 线性表的删除总结 2. 线性表的链…

JavaScript ES6+ 新特性

JavaScript ES6 新特性 引言 随着前端技术的不断发展&#xff0c;JavaScript 语言也在不断演进。自 ES6&#xff08;ES2015&#xff09;发布以来&#xff0c;JavaScript 引入了许多新的特性和语法&#xff0c;极大地提升了开发者的编程体验和代码的可维护性。本篇文章将详细探…

真话有危险,测评需谨慎!一个家最大的内耗:谁都在抱怨,没人肯改变——早读(逆天打工人爬取热门微信文章解读)

现在都这么完了吗&#xff1f; 引言Python 代码第一篇 洞见 一个家最大的内耗&#xff1a;谁都在抱怨&#xff0c;没人肯改变第二篇 故事风云录结尾 引言 慢慢调整时间 一是现在有点忙 做那个传播声音的研究实验实在是有点没有头绪 没有头绪的事情你就不知道怎么安排时间 也就…