JAVAEE-8-线程池

我们之前也接触过,比如说常量池,数据库连接池,线程池,进程池,内存池等等,

池的共性:

1.提前把要用的对象准备好

2.把用完的对象也不要立即释放,先留着以备下次使用

来提高效率!!!

最开始,进程能够解决并发编程的问题,因为频繁创建销毁进程的开销成本太大了,所以我们引进了轻量级进程===>线程.

如果销毁线程的频率进一步增大,那么此时线程的创建销毁开销成本,就不能再被无视了.

优化线程的创建销毁效率:

解决方案:

1.引入轻量级线程==>也称为纤程/协程

协程本质,是程序员在用户态代码进行调度,不是靠内核的调度器调度的,节省了很多调度上的开销.

协程是在用户代码中,基于线程封装出来的.有可能是n个协程对应着一个线程,也有可能是n个协程对应着M个线程.

2.线程池:

把要使用的线程提前创建好,用完了也不要直接释放而是以备下次使用,就节省了创建/销毁线程的开销.在这个使用的过程,并没有真的频繁创建销毁,而只是从线程池里,取线程使用,用完了放回线程池里而已.

从线程池里取代码,纯用户态代码,是可控的.

通过系统申请创建线程,就需要内核来完成的.(不太可控).

标准库中的线程池:
ThreadPoolExecutor

int corePoolSize 核心线程数:一个线程池里最少得有多少个线程

/**标准库中提供的线程数量并非是一成不变的.而是会根据当前任务量,自适应线程个数,任务多了,线程就会多几个,任务少了,线程就会少几个

int maximumPoolSize 最大线程数,一个线程池里,最多能有多少个线程

keepAliveTime是保持存活时间,成为实习生线程,就是允许最大的空闲摸鱼时间,如果当前的这个实习生线程,空闲超过了这个时间阈值,就会被销毁掉,

unit 单元变量,s/min/hour/ms

Runnable,作为描述任务的主体,和定时器类似,线程池中也可以有多个任务,也可以设置PriorityBlockingQueue,带有优先级

线程工厂,-->工厂模式,也是一种常见的设计模式.通过专门的"工厂类"/"工厂对象"来创建制定的对象

在这个类里面提供了方法(也不一定非得是静态的)

让方法封装了new操作,并且同时给Thread设置了一些属性,才构成了ThreadFactory线程工厂

工厂模式解析

//举例,表示平面上的一个点

class Point{

public Point(double x,double y);//通过笛卡尔积来初始化

public Point(double r,double a)';//通过极坐标来初始化

因为上述代码无法通过编译,所以我们设计工厂模式来解决上述问题}

class Point{

public static PointMakeByXY(double x,double y){

Point p=new Point();

p.setX(x);

p.setY(y);

}

public static PointMakeByra(double r,double a){

Point p=new Point();

p.setR(r);

p.setA(a);

}

Point p1=Point.PointMakeByxy(x,y);

Point p2=Point.PointMakeByra(r,a);

//工厂模式的核心思路,使用一些类或者对象来使用静态方法对new操作进行封装,然后再去单独的去设置他的一些属性,在方法内部设定不同的属性来完成对象的初始化,构造对象的过程.来达到我们想要的结果.

拒绝策略;

在线程池里,有一个阻塞队列,能够容纳的元素有上限,当任务队列已经满了的时候,如果继续往队列中添加任务,线程池会怎么办?

第一个,AbortPolicy:如果继续添加任务,他会直接抛出异常RejectedExecutionException,导致新的任务无法完成,旧的任务也无法完成了.

第二个:CallerRunsPolicy,新的任务,由添加任务的线程来负责执行,就是调用这个方法的线程去完成,不是线程池完成

第三个:DiscardOldesPolicy,丢弃最老的任务,新增加的任务会由线程池执行

第四个:DiscardPolicy,会把最新的任务丢弃掉,谁也不去执行,调用的线程不执行,线程池也不去执行.

ThreadPoolExecutor本身比较复杂,因此标准库提供了另外一个版本,把ThreadPoolExecutor进行了封装,封装成Executors,工厂类.通过这个类来创建出不同的线程池对象(在内部把ThreadPoolExecutor创建好了并且设置了不同的參数)

ExecutorService service=Executors.newFixedThreadPool(4);service.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello");}});

我们在实际开发中,创建线程池的时候,很多时候都需要去设定线程池的线程数量.

不同的程序,能够设定的线程的数量是不同的,必须要具体问题具体分析.

我们要判断一个线程是CPU密集型的任务还是IO密集型的任务.

对于CPU密集型的任务(这个线程大部分时间都要在CPU上运行,进行计算)

对于IO密集型任务(这个线程大部分的时间都在等待IO,不需要去CPU上运行),比如线程run,scanner,读取用户的输入.

如果一个进程中,所有的线程都是CPU密集型的,每个线程所有的工作都是CPU上执行的.(极端情况)

此时,线程数目就不该超过N(cpu逻辑核心数)

如果一个进程中,所有的线程都是IO密集型的,每个线程的大部分工作都是在等待IO,cpu消耗非常少,此时的线程数目就可以很多,远远超过N.

上述两个情况都是极端情况,在实际开发中,大概率是一部分是IO一部分是CPU的.

这里的比例,需要我们通过具体的实验测试出来.

综上,由于程序的复杂性,很难直接对于线程池的线程数目进行估算.

更适合的做法,通过实验/测试的方式来找到合适的线程数目.

尝试给线程池,设定不同的线程数目,分别进行性能测试.

衡量每种线程数目下,总的时间开销,和系统资源占用的开销,找到这两者之间合适的值.

自定义线程池创建

class MyThreadPoolExecutor{//自定义线程池private ArrayList<Thread>threadArrayList=new ArrayList<>();//用来存储后续设定的线程,方便后续处理private BlockingQueue<Runnable> queue=new ArrayBlockingQueue<>(4);//用来存储执行任务的队列public MyThreadPoolExecutor(int n){//n为线程池创建出来的线程数目for(int i=0;i<n;i++){Thread t=new Thread(()->{while(true){try {Runnable runnable=queue.take();//取出需要执行的任务,这里的队列使用take,是带有阻塞功能的runnable.run();//取出来之后进行使用} catch (InterruptedException e) {throw new RuntimeException(e);}}});threadArrayList.add(t);t.start();}}public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);//这里进行放入任务}}

测试代码

public class Main {public static void main(String[] args) throws InterruptedException {MyThreadPoolExecutor executor=new MyThreadPoolExecutor(4);for(int i=0;i<1000;i++){int n=i;//因为变量捕获executor.submit(new Runnable() {@Overridepublic void run() {System.out.println("执行任务"+n+"线程为"+Thread.currentThread().getName());}});}}
}

运行结果 

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

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

相关文章

新版Spring Security6.2案例 - Basic HTTP Authentication

前言&#xff1a; 书接上文&#xff0c;翻译官网Authentication的Username/Password这页&#xff0c;接下来继续翻译basic的这页&#xff0c;因为官网说的都是原理性的&#xff0c;这边一个小案例关于basic http authentication。 Basic Authentication 本节介绍 HTTP 基本身…

Unity 通过鼠标控制模拟人物移动和旋转视角

要通过鼠标控制并模拟人物移动和转换视角&#xff0c;将会使用射线检测、鼠标点击和鼠标水平移动&#xff0c;配合物体旋转和移动方法共同实现。 首先搭建个由一个Plane地板和若干cube组成的简单场景&#xff1a; 其次创建一个Capsule作为移动物体&#xff0c;并把摄像头拉到该…

腾讯云优惠券领取指南

腾讯云优惠券是降低云服务成本的有效手段&#xff0c;无论是新用户还是老用户&#xff0c;都可以通过下面方法领取到适合自己的优惠券。 1、腾讯云优惠券领取 领取入口&#xff1a;txy.ink 2、腾讯云优惠券介绍 腾讯云优惠券包括代金券和折扣券&#xff0c;代金券可以在结算…

【CCF BDCI 2023】多模态多方对话场景下的发言人识别 Baseline 0.71 CNN 部分

【CCF BDCI 2023】多模态多方对话场景下的发言人识别 Baseline 0.71 CNN 部分 概述CNN 简介数据预处理查看数据格式加载数据集 图像处理限定图像范围图像转换加载数据 CNN 模型Inception 网络ResNet 残差网络总结参数设置 训练 Train模型初始化数据加载训练超参数训练循环 验证…

Python 从入门到精通 学习笔记 Day04

Python 从入门到精通 第四天 今日目标 数据类型-又见str、数据类型-又见list 列表切片&排序&反转&循环、字典 数据类型 - 又见str 字符串定义 字符串是一个有序的字符的集合&#xff0c;用于在计算机里存储和表示文本信息 创建 a "Hello ,my name is Ha…

Android---Kotlin 学习005

substring 字符串截取。相加与 java&#xff0c;kt 里面的 substring 函数支持 IntRange 类型&#xff08;表示一个整数范围的类型&#xff09;的参数&#xff0c;until 创建的范围不包括上限值。 const val NAME "Jimmys friend" fun main(){val index NAME.ind…

TrustGeo代码理解(二)test.py

代码链接&#xff1a;https://github.com/ICDM-UESTC/TrustGeo 一、加载检查点&#xff08;checkpoint&#xff09;并进行测试 # -*- coding: utf-8 -*-"""load checkpoint and then test """ 该脚本的目的是加载之前训练过的模型的检查点&am…

【Linux】基于sed正则指令修改application.properties属性值

文章目录 背景sed介绍演示结果 背景 服务器上搭建了SpringCloud微服务&#xff0c;每个服务中都有application.properties文件&#xff0c;在部署过程中需要修改每个微服务的redis.ip和redis.port。如果手动去修改会很麻烦&#xff0c;所以下面写了一个shell脚本&#xff08;基…

idea的快捷键

1.调整字体的大小 文件夹的循序:setting-Editor-Font 界面: 2.删除当前行 文件夹的循序:setting-Keymap-DeleteLine 界面: 3.导入该行需要的类 文件夹的循序:setting-Editor-General-Auto import 界面: 4.格式化代码 文件夹的循序:setting-keymap-Reformat 界面: 5.快速…

大模型微调方法:冻结方法 Freeze、P-Tuning 系列、LoRA、QLoRA

大模型微调方法 冻结方法 FreezeP-Tuning 系列Prefix-TuningPrompt TuningP-Tuning v1P-Tuning v2 LoRAQLoRA 冻结方法 Freeze 方法意思是&#xff0c;只用少部分参数训练&#xff0c;把模型的大部分参数冻结。 只要设置微调层的参数&#xff1a; # 遍历模型的所有参数和名称…

程序员的养生之道:延寿健康的十大秘诀(下)

程序员的养生之道&#xff1a;延寿健康的十大秘诀&#xff08;上&#xff09;-CSDN博客 目录 6. 心理调节&#xff0c;减轻压力 6.1 程序员常见的心理问题 6.2 压力管理的重要性 6.3 放松技巧与应对策略 6.4 积极心态与心理健康 7. 正确坐姿&#xff0c;保护颈椎腰椎 …

VLAN协议与单臂路由

文章目录 VLAN协议与单臂路由一、VLAN的概念及优势1、分割广播域2、VLAN的优势3、VLAN数据帧 二、VLAN的种类1、静态VLAN2、动态VLAN3、VLAN划分方式 三、静态VLAN的配置1、VLAN的范围2、静态VLAN的配置2.1 配置静态VLAN的步骤2.2 vlan三种端口类型举例&#xff1a;配置静态VLA…

VR全景直播来临,沉浸式代入吸引百万人目光

如今&#xff0c;VR技术正在不断改变着直播行业的面貌&#xff0c;为观众提供沉浸式的观看体验。在5G技术的快速发展背景下&#xff0c;VR全景直播作为5G应用的场景&#xff0c;被广泛应用在体育赛事、新闻会议、演唱会、教育医疗等场景&#xff0c;通过VR技术进行全景直播&…

c语言结构体调用格式与对齐

1.声明形式&#xff1a; struct 结构体名字 { 结构体成员 }结构体变量名&#xff1b; 2.赋值方法 3.结构体对齐&#xff1a; 1.起始偏移量&#xff1a;默认结构体第一个元素对齐0起始偏移量&#xff0c;第一个元素占一个字节&#xff0c;此时偏移量为1. 2.标准数&#xff…

基于stm32 FP-AUD-SMARTMIC1 音频系统开发

基于stm32 FP-AUD-SMARTMIC1 音频系统开发 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群赠送语音信号处理降噪算法,蓝牙耳机音频,DSP音频项目核心开发资料, FP-AUD-SMARTMIC1 是一个用于 STM32F4Discovery …

《使用ThinkPHP6开发项目》 - 创建控制器

《使用ThinkPHP6开发项目》 - 安装ThinkPHP框架-CSDN博客 《使用ThinkPHP6开发项目》 - 设置项目环境变量-CSDN博客 《使用ThinkPHP6开发项目》 - 项目使用多应用开发-CSDN博客 《使用ThinkPHP6开发项目》 - 创建应用-CSDN博客 使用ThinkPHP6创建控制器&#xff0c;开始项…

css 纯样式实现绘出进度条

效果&#xff1a; css代码&#xff1a; .bar{height: 14px;width: 100%;font-size: 10px;margin-top: 5px;background-color: #f5f5f5;}.bar::before{display: block;counter-reset: progress var(--precent); content: ;width: calc(1% * var(--precent));color: #fff;height:…

【C++进阶篇】二叉搜索数

目录 前言&#xff1a; 以后我们要学map&#xff0c;set&#xff0c;AVL&#xff0c;红黑数所以必须要有二叉搜索数做铺垫 1、二叉搜索树概念 2.二叉搜索树操作 1.二叉搜索树的查找 a、从根开始比较&#xff0c;查找&#xff0c;比根大则往右边走查找&#xff0c;比根小则…

SpringBoot 实现动态切换数据源

最近在做业务需求时&#xff0c;需要从不同的数据库中获取数据然后写入到当前数据库中&#xff0c;因此涉及到切换数据源问题。本来想着使用Mybatis-plus中提供的动态数据源SpringBoot的starter&#xff1a;dynamic-datasource-spring-boot-starter来实现。 结果引入后发现由于…

IO零拷贝

在介绍零拷贝之前我们先看看传统的 Java 网络 IO 编程是怎样的。 下面代码展示了一个典型的 Java 网络程序。 File file new File("index.jsp");RandomAccessFile rdf new RandomAccessFile(file, "rw");byte[] arr new byte[(int) file.length()];rdf…