当前位置: 首页 > news >正文

多线程应用——线程池

线程池

文章目录

  • 线程池
    • 1.什么是线程池
    • 2.为什么要用线程池
    • 3.怎么使用线程池
    • 4.工厂模式
    • 5.自己实现一个线程池
    • 6.创建系统自带的线程池
      • 6.1 拒绝策略
      • 6.2 线程池的工作流程

1.什么是线程池

字面意思,一次创建多个线程,放在一个池子(集合类),用的时候拿一个,用完了之后就放回这个池子就可以了。

2.为什么要用线程池

  1. 首先使用多线程编程就是为了提高效率,势必会创建很多线程,创建的过程是JVM通过调用系统API来申请系统的过程,虽然说创建线程的开销要比创建进程的开销要小的多,但是也架不住特别频繁的创建和销毁,而池化技术就可以减少线程的频繁创建与销毁,从而提高程序性能
  2. JVM调用系统API就意味着从用户态到内核态去执行,而一个系统只有一个内核态,这个内核需要处理很多的事情,所有的进程都是要兼顾到的

因此使用线程池的最主要的目的是为了提高效率,尽量减少从用户态到内核态的切换

3.怎么使用线程池

JDK中提供了一组不同的线程池的实例

public class Demo01 {public static void main(String[] args) {// 1. 用来处理大量短时间工作任务的线程池,如果池中没有可用的线程将创建新的线程,如果线程空闲60秒将收回并移出缓存ExecutorService cachedThreadPool = Executors.newCachedThreadPool();// 2. 创建一个操作无界队列且固定大小线程池ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);// 3. 创建一个操作无界队列且只有一个工作线程的线程池ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();// 4. 创建一个单线程执行器,可以在给定时间后执行或定期执行。ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();// 5. 创建一个指定大小的线程池,可以在给定时间后执行或定期执行。ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);// 6. 创建一个指定大小(不传入参数,为当前机器CPU核心数)的线程池,并行地处理任务,不保证处理顺序Executors.newWorkStealingPool();}
}

以上方法都是用来获取线程池对象的,通过不同的工厂方法获取不同功能的线程池。

4.工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

为什么要使用工厂模式

这里我们用一个简单的例子来说明原因

public class Factory {public static void main(String[] args) {Student student = Student.createByAgeAndName(20, "张三");System.out.println(student);}
}
class Student{private int id;private int age;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Student() {}public Student(int id, String name) { this.id = id;this.name = name;}public Student(int age, String name) {this.age = age;this.name = name;}}

观察上述代码,观察一下有什么问题,当我们想通过id或者age来创建一个学生类时,利用构造方法来创建时,出现了'Student(int, String)' is already defined in... 这里的语法不符合Java语法中重载的语法规则,因此我们使用工厂模式可以解决这类问题。

public class Factory {}
class Student{private int id;private int age;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Student() {}// 通过方法名的区分来分别实现不同的创建对象的方法public static Student createByIdAndName(int id,String name){Student student=new Student();student.setId(id);student.setName(name);return student;}public static Student createByAgeAndName(int age,String name){Student student=new Student();student.setAge(age);student.setName(name);return student;}}

对于工厂模式可以参考以下教程 工厂模式

5.自己实现一个线程池

实现步骤:

  1. 管理任务的一个队列,可以用阻塞队列去实现,使用阻塞队列的好处是,当线程去取任务时,如果队列为空那么就阻塞等待,不会造成过多的CPU资源消耗
  2. 提供一个往队列中添加任务的方法
  3. 创建多个线程,扫描这个队列,如果有任务就拿出来执行
public class MyThreadPool{//定义一个阻塞队列来管理任务BlockingQueue<Runnable>queue=new LinkedBlockingQueue<>();/*** 提供一个往队列中添加任务的方法* @param runnable* @throws InterruptedException*/public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}/*** 提供一个指定了创建线程数的构造方法* @param num*/public MyThreadPool(int num){if(num<=0){throw new RuntimeException("线程数必须大于0");}// 创建线程for (int i = 0; i < num; i++) {Thread thread = new Thread(() -> {while (true){try {Runnable runnable=queue.take();runnable.run();} catch (InterruptedException e) {e.printStackTrace();}}});//启动线程thread.start();}}
}

6.创建系统自带的线程池

在开发过程中一般使用ThreadPoolExecutor这个类来创建线程池,以下为每个参数的代表意义

pool

代码实现

public class Demo {public static void main(String[] args) {ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,//核心线程数10,//最大线程数1,//临时线程的存活时间TimeUnit.SECONDS,//临时线程的存活时间单位new LinkedBlockingQueue<>(20),//阻塞队列的类型和大小);for (int i = 0; i < 100; i++) {int taskId=i;threadPoolExecutor.submit(()->{System.out.println("执行任务 " +taskId+",当前线程:"+Thread.currentThread().getName());});}}
}

6.1 拒绝策略

image-20230906175334118

6.2 线程池的工作流程

image-20230906175032534
关于线程池的分享就到这里了,看完留下的你们的三连吧,你们的支持是我最大的动力!!!

相关文章:

多线程应用——线程池

线程池 文章目录 线程池1.什么是线程池2.为什么要用线程池3.怎么使用线程池4.工厂模式5.自己实现一个线程池6.创建系统自带的线程池6.1 拒绝策略6.2 线程池的工作流程 1.什么是线程池 字面意思&#xff0c;一次创建多个线程&#xff0c;放在一个池子(集合类)&#xff0c;用的时…...

OPENCV+QT环境配置

【qtopencv开发入门&#xff1a;4步搞定opencv环境配置2】https://www.bilibili.com/video/BV1f34y1v7t8?vd_source0aeb782d0b9c2e6b0e0cdea3e2121eba 第一步&#xff1a; 安装QT Qt 5.15 第二步&#xff1a; 安装OPENCV VS2022 Opencv4.5.5 C 配置_愿飞翔的鱼儿的博客…...

Kafka3.0.0版本——文件清理策略

目录 一、文件清理策略1.1、文件清理策略的概述1.2、文件清理策略的官方文档1.3、日志超过了设置的时间如何处理1.3.1、delete日志删除&#xff08;将过期数据删除&#xff09;1.3.2、compact日志压缩 一、文件清理策略 1.1、文件清理策略的概述 Kafka 中默认的日志保存时间为…...

SRT参数说明

1.超时选项 connect_timeout 连接超时时间&#xff0c;单位毫秒&#xff0c;默认值为3秒。 当RTT > 1500毫秒(2次握手交换)时&#xff0c;SRT无法连接。此选项适用于caller和rendezvous模式。 listen_timeout 监听超时时间&#xff0c;单位毫秒 timeout 为读、写和连接操作…...

vue响应式原理

vue响应式原理 vue响应式原理vue2响应式原理目标对象为数组时 vue3响应式原理Vue3和Vue2在响应式系统方面的对比数据劫持的方式支持数据劫持的数据类型Vue3响应式系统显著优点是&#xff1a; vue响应式原理 无论vue2和vue3响应式都是通过观察者模式&#xff08;发布订阅模式&a…...

elk安装篇之 Kibana安装

Kibana是一个开源的分析与可视化平台&#xff0c;设计出来用于和Elasticsearch一起使用的。你可以用kibana搜索、查看存放在Elasticsearch中的数据。是es的可视化客户端之一。 一&#xff1a;下载 https://www.elastic.co/cn/kibana 我的es是elasticsearch-7.10.2版本&#x…...

MySQL 用户授权管理及白名单

1.创建用户 在 MySQL 中&#xff0c;你可以通过以下步骤创建用户并设置白名单&#xff1a; 使用管理员账号连接到 MySQL 服务器。 创建新用户&#xff1a; CREATE USER usernamehostname IDENTIFIED BY password;其中&#xff0c; username 是你要创建的用户名&#xff1b;ho…...

pc-签字画板vue-esign的使用

使用的是vue-esign组件 npm install vue-esign 首先下载组件在main.js中引入vue-esign&#xff0c;并且挂载 import { createApp } from vue; import App from ./App.vue; const app createApp(App);import vueEsign from vue-esign app.use(vueEsign ) 页面使用&#xff0…...

javaScript:节点操作

目录 前言 常用的节点操作 innerHTML 的两个弊端&#xff08;补充&#xff09; createElement(标签名)使用dom方法创建一个元素 父元素.appendChild(子元素) 添加到父元素 注意 指定插入 父元素.insertBefore(要添加的元素&#xff0c;父元素中的指定子元素) 注意&…...

git 忽略已经提交的文件或文件夹 (修改.gitignore文件无效)

场景描述&#xff1a;项目开发到一半&#xff0c;追加了模块&#xff0c;提交的时候未注意将不需要提交的文件或者目录提交到.gitignore&#xff0c;然后提交后发现再修改git配置文件已无法阻拦更新&#xff0c;查阅官方资料&#xff1a; 核心点&#xff1a;.gitignore 之前&a…...

学习左耳听风栏目90天——第十二天 12/90(学习左耳朵耗子的工匠精神,对技术的热爱)【时间管理:同扭曲时间的事儿抗争】

时间管理&#xff1a;同扭曲时间的事儿抗争 要学会说不...

前端如何将后台数组进行等分切割

前端如何切割数组 目标&#xff1a;前端需要做轮播&#xff0c;一屏展示12个&#xff0c;后端返回的数组需要进行切割&#xff0c;将数据以12为一组进行分割 环境&#xff1a;vue3tselement plus 代码如下&#xff1a; function divideArrayIntoEqualParts(array, chunkSiz…...

如何有效防止服务器被攻击?

随着互联网的快速发展&#xff0c;服务器安全问题日益引起人们的关注。近期&#xff0c;全球范围内频繁发生的服务器攻击事件引发了广泛关注。为了保护企业和个人的数据安全&#xff0c;有效防止服务器被攻击已成为迫在眉睫的任务。 首先&#xff0c;及时更新服务器的操作系统和…...

layui表格高度

layui表格的高度设置时使用 height:‘full’ 高度就是表格每个页面的总高度。也可以直接写数值&#xff0c;但是这是定高。 也可以使用 height&#xff1a;“full-数值”&#xff0c;比如 height:full-80 那么就会在表格占据剩余div的时候底部留100px。相当于margin-bottom:10…...

一文1800字从0到1使用Python Flask实战构建Web应用

Python Flask是一个轻量级的Web框架&#xff0c;它简单易用、灵活性高&#xff0c;适用于构建各种规模的Web应用。本文将介绍如何使用Python Flask框架来实战构建一个简单的Web应用&#xff0c;并展示其基本功能和特性。 第一部分&#xff1a;搭建开发环境 在开始之前我们需要…...

【LeetCode-中等题】210. 课程表 II

文章目录 题目方法一&#xff1a;bfs方法二&#xff1a;dfs 题目 这一题是在207题的基础上&#xff0c;要统计拓扑排序的顺序集合&#xff0c;所以只需要在207的基础上加入一个将拓扑排序的节点输出即可&#xff08;有环无拓扑排序&#xff09; 【LeetCode-中等题】207. 课程表…...

vue修饰符的用法

Vue修饰符是指在Vue模板中用于改变指令行为的特殊后缀。修饰符以.开头&#xff0c;用于指示指令应该如何绑定或响应事件。Vue修饰符在一些常见的指令中使用&#xff0c;例如v-on和v-model。常见的Vue修饰符包括&#xff1a; .prevent&#xff1a;阻止默认事件的发生。.stop&am…...

汽车3D HMI图形引擎选择

2002年,电影《少数派报告》让观众深入了解未来。 除了情节的核心道德困境之外,大多数人都对它的技术着迷。 我们看到了自动驾驶汽车、个性化广告和用户可以无缝交互的 3D 计算机界面。 令人惊讶的是,虽然故事发生在 2054 年,但许多科幻想象的作品已经成为现实。 对于汽车和…...

stable diffusion实践操作-webUI教程-不是基础-是特例妙用

系列文章目录 stable diffusion实践操作 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、SD webUI是什么&#xff1f;二、详细教程1. 相关插件安装1.1. 提示词插件安装和使用1.2 tagg标签妙用…...

【Java】网络编程

网络编程 Socket套接字概念分类Java数据报套接字通信模型一次发送和接受UDP数据报提供多个客户端的请求处理及响应 Java流套接字通信模型Socket编程注意事项 UDP数据报套接字编程DatagramSocket API构造方法普通方法 DatagramPacket API构造方法普通方法 InetSocketAddress API…...

van-cascader 异步加载

vant官网 异步加载选项 在使用级联选择时当一次性拿到数据量太大时不仅接口慢而且前端渲染页面也会变慢&#xff0c;用户体验很不好&#xff0c;建议使用异步加载选项&#xff0c; 拿到的接口让后端返回一个是否还有下一级的判断&#xff0c;不然van-cascader判断没有childre…...

Golang单元测试举例

1.第一个例子 cal.go package mainfunc addUpper(n int) int {res : 0for i : 1; i < n; i {res i}return res }func getSub(n1 int, n2 int) int {return n1 - n2 }cal_test.go package main//测试文件名必须是_test.go结尾 //测试函数必须Test开头 import ("fmt…...

汽车以太网协议栈

《大师说》栏目上线啦# 《大师说》栏目是怿星科技2023年推出的深度思考栏目&#xff0c;通过邀请内部专家&#xff0c;针对智能汽车行业发展、技术趋势等输出个性化的观点。每期一位大师&#xff0c;每位一个话题&#xff0c;本期由我们怿星的CTO虞胜伟&#xff0c;进行分享。…...

数学建模--二次规划型的求解的Python实现

目录 1.算法流程简介 2.算法核心代码 3.算法效果展示 1.算法流程简介 #二次规划模型 #二次规划我们需要用到函数:Cvxopt.solvers.qp(P,q,G,h,A,b) #首先解决二次规划问题和解决线性规划问题的流程差不多 """ 求解思路如下: 1.针对给定的代求式,转化成标准式…...

Ansible-palybook学习

目录 一.playbook介绍二.playbook格式1.书写格式2.notify介绍 一.playbook介绍 playbook 是 ansible 用于配置&#xff0c;部署&#xff0c;和管理被控节点的剧本。通过 playbook 的详细描述&#xff0c;执行其中的一系列 tasks &#xff0c;可以让远端主机达到预期的状态。pl…...

服务注册与服务发现

服务注册与服务发现 Eureka的架构 Eureka客户端&#xff1a;使用了EnableEurekaClient注解的应用服务&#xff0c;如订单服务等&#xff0c;甚至Eureka本身也是一个客户端 Eureka服务端&#xff1a;使用了EnableEurekaServer注解的应用服务&#xff0c;该服务提供了注册表以及…...

RabbitMQ从入门到精通之安装、通讯方式详解

文章目录 RabbitMQ一、RabbitMQ介绍1.1 现存问题 一、RabbitMQ介绍二、RabbitMQ安装三、RabbitMQ架构四、RabbitMQ通信方式4.1 RabbitMQ提供的通讯方式4.2 Helloworld 方式4.2Work queues4.3 Publish/Subscribe4.4 Routing4.5 Topics4.6 RPC (了解) 五、Springboot 操作RabbitM…...

植物大战僵尸植物表(二)

前言 此文章为“植物大战僵尸”专栏中的第007刊&#xff08;2023年9月第六刊&#xff09;。 提示&#xff1a; 1.用于无名版&#xff1b; 2.用于1代&#xff1b; 3.pvz指植物大战僵尸&#xff08;Plants VS Zonbies)。 植物大战僵尸植物表 土豆雷窝瓜火炬树桩火爆辣椒杨…...

UML基础

统一建模语言&#xff08;UML是 Unified Modeling Language的缩写, 是用来对软件系统进行可视化建模的一种语言。UML为面向对象开发系统的产品 进行说明、可视化、和编制文档的一种标准语言。 共有9种图 UML中的图其实不止九种 (相同的图还可能会有不同的名称), 这里的九种图是…...

C# void 关键字学习

C#中void关键字是System.Void的别名&#xff1b; 可以将 void 用作方法&#xff08;或本地函数&#xff09;的返回类型来指定该方法不返回值&#xff1b; 如果C&#xff03;方法中没有参数&#xff0c;则不能将void用作参数&#xff1b;这是与C语言不同的&#xff0c;C语言有…...