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() {
            @Override
            public 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() {
                @Override
                public void run() {
                    System.out.println("执行任务"+n+"线程为"+Thread.currentThread().getName());
                }
            });
        }
    }
}

运行结果 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Jenkins】Centos环境安装Jenkins(通过docker安装)

通过docker环境安装Jenkins 参考官网 https://hub.docker.com/r/jenkins/jenkins/ 1、安装docker环境 # 删除已有安装包 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-…

正确看待鸿蒙不兼容Android,这不是趋势?

华为可能明年推出不兼容安卓的鸿蒙版本。11月20日&#xff0c;据澎湃新闻报道&#xff0c;一华为相关人士表示&#xff0c;推出时间还不确定&#xff0c;未来IOS、鸿蒙、安卓将为三个各自独立的系统。 稍早前据证券时报报道&#xff0c;有业内人士亦表示&#xff1a;“华为内部…

测试面试必备:HTTP请求和响应详解!

一次完整的HTTP请求过程从TCP三次握手建立连接成功后开始&#xff0c;客户端按照指定的格式开始向服务端发送HTTP请求&#xff0c;服务端接收请求后&#xff0c;解析HTTP请求&#xff0c;处理完业务逻辑&#xff0c;最后返回一个HTTP的响应给客户端&#xff0c;HTTP的响应内容同…

Ubuntu与Windows通讯传输文件(FTP服务器版)(没用的方法,无法施行)

本文介绍再Windows主机上建立FTP服务器&#xff0c;并且在Ubuntu虚拟机上面访问Windows上FTP服务器的方法 只要按照上图配置就可以了 第二部&#xff1a;打开IIS管理控制台 右击网站&#xff0c;新建FTP站点。需要注意的一点是在填写IP地址的时候&#xff0c;只需要填写Window…

matlab操作方法(三)——matlab中的数字图像(读取、显示、保存)

数字图像是二维图像用有限数字数值像素的表示。通常像素在计算机中保存为二维整数数组的光栅图像&#xff0c;这些值经常用压缩格式进行传输和存储。 二值图像&#xff1a;图像中每个像素的亮度值仅可以取自0或1的图像&#xff0c;因此也称为1bit图像 灰度图像&#xff1a;图…

【数据结构】贪心算法

一.贪心算法的定义 贪心算法是指在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&#xff0c;只做出在某种意义上的局部最优解。 贪心算法的结果是最优解的最好近似。 优点&#xff1a;简单&#xff0c;高效。 缺点&…

《Mamba: Linear-Time Sequence Modeling with Selective State Spaces》阅读笔记

论文标题 《Mamba: Linear-Time Sequence Modeling with Selective State Spaces》 利用选择性状态空间的线性时间序列建模 作者 Albert Gu 和 Tri Dao Albert Gu 来自卡内基梅隆大学机器学习系&#xff0c;Mamba 脱胎于 Albert Gu 的前作 S4 架构。 Tri Dao 来自普林斯顿…

赛氪为第五届全球校园人工智能算法精英大赛决赛提供技术支持

12月10日&#xff0c;以“智青春算未来”为主题的2023年第五届全球校园人工智能算法精英大赛全国总决赛在河海大学江宁校区举行。本次大赛由江苏省人工智能学会主办&#xff0c;自9月份启动以来&#xff0c;共吸引了全国近400所高校的3000多支参赛团队参加。经过校赛、省赛选拔…

C语言:高精度除法(除低精度)

P1480 A/B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 由图知&#xff0c;被除数的上一位的余数乘10加这位就是这一位结果的除数。 c[i] (d * 10 a[i]) / b #include<stdio.h> #include<string.h> char x[50005];//存储被除数&#xff0c;转为字符…

二百一十七、Flume——Flume拓扑结构之聚合的开发案例(亲测,附截图)

一、目的 对于Flume的聚合拓扑结构&#xff0c;进行一个开发测试 二、聚合 &#xff08;一&#xff09;结构含义 这种模式是我们最常见的&#xff0c;也非常实用。日常web应用通常分布在上百个服务器&#xff0c;大者甚至上千个、上万个服务器产生的日志&#xff0c;处理起来…

Java基础:如何创建多层文件夹

一、单层多个 代码实现如下&#xff1a; public class Main {public static void main(String[] args) {//在D盘中创建File file new File("D:"File.separator"docum");file.mkdir();//在D盘中的docum目录中创建file new File("D:\\docum" Fi…

[pasecactf_2019]flask_ssti proc ssti config

其实这个很简单 Linux的/proc/self/学习-CSDN博客 首先ssti 直接fenjing一把锁了 这里被加密后 存储在 config中了 然后我们去config中查看即可 {{config}} 可以获取到flag的值 -M7\x10wd94\x02!-\x0eL\x0c;\x07(DKO\r\x17!2R4\x02\rO\x0bsT#-\x1cZ\x1dG然后就可以写代码解…

Vue表格自定义合计、小计功能

一、合计 <template> <avue-crud:option"optiondata":table-loading"loading":data"testdata":page.sync"page":span-method"spanMethod"ref"cruddata"current-change"currentChangedata"si…

Unity | Shader基础知识(第四集:Shader结构体)

一、本节介绍 上一集&#xff0c;我们做了一个案例&#xff0c;这一集&#xff0c;我们继续讲一个语法&#xff0c;在shader里写结构体。 二、结构体的需求 1.shader里是不好随便去声明数据的&#xff0c;我们前面传入数据时&#xff0c;用的是括号传入&#xff08;如图&…

Redis怎么测?这篇文章写的太全了

Redis是一个高性能、内存数据库和缓存系统&#xff0c;在开发和生产环境中被广泛应用。本文将介绍如何进行有效的Redis软件测试&#xff0c;以确保其稳定性、高性能和可靠性。 Redis作为一种非关系型数据库和缓存系统&#xff0c;被广泛用于支持高流量、低延迟的应用。为了保证…

iic应用篇

一.iic的优点 1. IIC总线物理链路简单&#xff0c;硬件实现方便&#xff0c;扩展性非常好&#xff08;1个主机控制器可以根据需求增加从机数量&#xff0c;同时删减从机数量也不会影响总线通信&#xff09;&#xff1b;IIC总线只需要SDA和SCL两条信号线&#xff0c;相比于PCI/…

锂电池基础知识及管理方式总结

这两天在排查一个锂电池无法充电的问题&#xff0c;用的是电池管理芯片BQ25713&#xff0c;网上相关的资料也很少&#xff0c;查看数据手册时&#xff0c;里面也有很多术语参数等不是很理解&#xff0c;所以&#xff0c;在此对锂电池的基础知识做个简单的总结&#xff0c;方面后…

详解Django+Vue+Docker搭建接口测试平台实战

一. 开头说两句 正好接口自动化测试平台需要迁移到新的测试服务器上&#xff0c;就想要体验一番Docker的“一次构建&#xff0c;处处运行”。这篇文章简单介绍了下这次部署的过程&#xff0c;其中使用了Dockerfile定制镜像和Docker-Compose多容器编排。 二. 项目介绍 项目采…

Python-乒乓球小游戏【附完整源码】

乒乓球小游戏 乒乓球小游戏是一个简单而有趣的2D页面交互式游戏&#xff0c;玩家可以通过键盘输入来控制球拍上下移动来接球&#xff0c;从而体验乒乓球的乐趣。该游戏有单人和双人两种模式 运行效果&#xff1a; 一&#xff1a;主程序&#xff1a; import sys import cfg …

app自动化测试(Android)

Capability 是一组键值对的集合&#xff08;比如&#xff1a;"platformName": "Android"&#xff09;。Capability 主要用于通知 Appium 服务端建立 Session 需要的信息。客户端使用特定语言生成 Capabilities&#xff0c;最终会以 JSON 对象的形式发送给 …