9.4 多线程之线程池

news2024/9/28 5:32:51

线程池

进程已经能做到并发编程了 , 为什么还需要线程 ?
进程实在是太重量了 , 创建和销毁成本都比较高 , 需要申请释放资源
线程就是针对上述问题的优化 , 因为他是共用同一组系统资源的 , 一旦资源申请好了 , 后续就不需要再继续申请了

虽然线程已经很好了 , 不过在更高频率下的创建释放的情况下 , 线程也就扛不住了
所以还需要进一步优化 :

1. 线程池
2. 协程 (也叫做纤程) , 更加轻量级的线程

我们主要研究一下线程池 :
线程池解决的思路就是把线程创建好之后 , 放到池子中 , 而不是通过系统来销毁
当线程用完了 , 还是还回到池子中 , 而不是通过系统来进行销毁

上述操作 , 就又进一步的提高效率了

那为什么把线程放到池子里 , 然后从池子中取出线程就要比从系统中创建线程来得快呢 ?

如果是从系统这里创建线程, 需要调用系统api, 进一步的由操作系统内核完成线程创建(内核态, 内核是给所有的进程提供服务的, 不可控的)

如果是从线程池这里获取线程, 上述的内核中进行的操作, 都提前做好了, 直接靠用户代码完成线程获取(用户态, 可控)

标准库中的线程池image.png

  

 线程池对象创建好后, 使用submit 方法, 就可以把任务添加到线程池中

public class Demo24 {
    public static void main(String[] args) {
        // ExecutorService 叫做执行器服务
        // Executors.newFixedThreadPool() 创建固定线程个数的线程池
        // Executors 是静态方法
        // Executors 通过.的方式调用静态方法

        // 固定个数的线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(10);

        // 线程数量动态增加的线程池
        // Executors.newCachedThreadPool();

        // 把任务加入到线程池中
        // 与定时器类似,线程池内部也有线程阻止退出,我们需要手动关闭
        threadPool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 线程池");
            }
        });
    }
}

经典面试题

如果把线程池比喻成公司, 核心线程数就是正式员工数量. 最大线程数就是正式员工 + 实习生 的数量

当公司业务不忙的时候, 就不需要实习生; 当公司业务繁忙的时候, 就找些实习生来分配任务.

不忙的时候再裁掉.

 

 

 

              官方提供一下拒绝策略(重点):

                        

                          

                        

                         

 第二个和第四个的区别在于第四个策略中新任务完全不会执行, 第二个中还会执行新任务

  自己实现线程池

 阻塞队列来保存一些任务 , submit 方法给线程池添加任务 , 线程池内部再持有一些线程来消费执行这里的任务

线程池就相当于一个简单的生产者-消费者模型

class MyThreadPool {
    // 由于插入任务可以一次性插入很多.需要能够把当前尚未执行的任务都保存起来 -> 队列
    // 这个队列就是一个任务队列,把当前线程池中要完成的内容都放到这个队列里
    // 再由线程池内部的工作线程负责完成他们
    private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();

    // 通过这个方法, 来把任务添加到线程池中.
    public void submit(Runnable runnable) throws InterruptedException {
        queue.put(runnable);
    }

    // 构造方法中,就需要创建一些线程,让这些线程负责完成上述执行任务的工作
    // n 表示线程池里有几个线程.
    // 创建了一个固定数量的线程池.
    public MyThreadPool(int n) {
        for (int i = 0; i < n; i++) {
            Thread t = new Thread(() -> {
                while (true) {
                    try {
                        // 取出任务, 并执行~~
                        Runnable runnable = queue.take();
                        runnable.run();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            t.start();
        }
    }
}

// 线程池
public class Demo24 {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPool pool = new MyThreadPool(4);
        for (int i = 0; i < 1000; i++) {
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    // 要执行的工作
                    System.out.println(Thread.currentThread().getName() + " hello");
                }
            });
        }
    }
}

 此时线程的调度是随机的 

当前给这个线程池插入的任务,  在执行的时候, 也不一定是N个线程的工作量完全相等

但是从统计意义上说, 任务栏均等~

创建线程池的时候, 线程个数是咋确定的?

MyThreadPool pool = new MyThreadPool(4);

线程池的线程数目网上查资料, 你能看到很多种说法

比如, 假设cpu核数为N , 线程池线程个数: N N + 1 , 1.2 * N , 1.5 * N , 2 * N 这个说法不准确

不同项目中, 线程要做的工作是不一样的:

有的线程的工作, 是"CPU密集型", 线程的工作全是运算

大部分工作都要在CPU上完成, CPU得给工作安排核心后工作才有进展

如果CPU是N个核心, 当你线程数量也是N的时候, 理想情况就是每个核心上有一个线程

如果搞很多线程,  线程也就是在排队等待, 不会有新的进展

有的线程的工作, 是" IO密集型" , 读写文件, 等待用户输入, 网络通信

涉及大量的等待时间(等用户) 等的过程中, 没有使用CPU

这样就算线程更多一些, 也不会给CPU造成太大的负担

比如CPU是16个核心, 写32 个线程 由于是IO密集的

这里大部分线程都在等, 都不消耗CPU, 反而CPU的占用情况还很低

实际开发中, 一个线程往往是一部分工作是CPU密集的, 一部分工作是IO密集的

此时一个线程几成是在CPU上, 几成是在等待IO说不好

更好的做法是通过实验的方式, 来找到合适的线程数,

性能测试尝试不同的线程数目 找到性能和系统资源开销比较均衡的线程数 

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

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

相关文章

浙大全日制英文MBA项目提面申请截至9月3日:几乎是上岸必经之路

今年浙大全日制MBA项目提前批面试做了改革&#xff0c;一年只设定一个批次申请&#xff0c;对于考生们来说其实是不太有利的&#xff0c;原因在于整个提面时间节奏会将部分考生逼到进退两难的境地&#xff0c;一方面无提面的状态下全日制MBA项目都知道需要比较高的分数才可能够…

计算机竞赛 基于CNN实现谣言检测 - python 深度学习 机器学习

文章目录 1 前言1.1 背景 2 数据集3 实现过程4 CNN网络实现5 模型训练部分6 模型评估7 预测结果8 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于CNN实现谣言检测 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&am…

GC的前置工作,聊聊GC是如何快速枚举根节点的

本文已收录至GitHub&#xff0c;推荐阅读 &#x1f449; Java随想录 原创不易&#xff0c;注重版权。转载请注明原作者和原文链接 文章目录 什么是根节点枚举根节点枚举存在的问题如何解决根节点枚举的问题安全点安全区域 上篇文章中我们留下了个坑&#xff1a;「 根节点枚举」…

计网第三章(数据链路层)(四)

目录 一、MAC地址和IP地址以及ARP协议 1.MAC地址&#xff1a; 单播MAC地址&#xff1a; 广播MAC地址&#xff1a; 多播MAC地址&#xff1a; 2.IP地址&#xff1a; 3.IP地址和MAC地址&#xff1a; 1.什么情况下使用&#xff1f; 2.IP地址和MAC地址填写位置&#xff1f;…

保障用户观影体验 极米推出首款搭载超级混光技术投影仪极米RS Pro 3

随着投影市场的日渐蓬勃&#xff0c;倒推了投影技术的研发创新&#xff0c;投影仪产品在最近几年已经逐步进入到家庭空间&#xff0c;成为很多家庭不可或缺的家电产品&#xff0c;不论是客厅还是卧室&#xff0c;或者是户外露营等&#xff0c;投影仪的家用场景已经拓展到了人们…

ps2024后期调色滤镜插件使用教程图解

Exposure是一款常见的ps调色滤镜插件&#xff0c;相信许多朋友都曾经用过它。一个优秀的摄像师不仅需要懂得摄像技巧&#xff0c;还要掌握图像的后期调色窍门。那么&#xff0c;后期调色软件哪个好&#xff0c;后期调色教程图解&#xff0c;接下来一起来了解一下吧。 一、后期…

为何Ping不通啊?

为什么Ping不通啊&#xff01;求指点&#xff1f; 友情提醒&#xff0c;这个问题难度系数初级难度&#xff08;CCNA&#xff09;&#xff0c;只适合初级读者阅读&#xff0c;避免浪费宝贵时间。 Q1: 为何PC1能Ping通PC2&#xff1f;或反之亦然&#xff1f; PC1主观认为PC2和自…

YOLO目标检测——血管瘤数据集下载分享

血管瘤数据集在医学领域的研究和临床应用中起着重要的作用。它可以用于开发和评估血管瘤检测和分割算法&#xff0c;帮助医生准确地定位和诊断血管瘤。此外&#xff0c;血管瘤数据集还可以用于研究血管瘤的生长规律、预测血管瘤的发展趋势等。 数据集点击下载&#xff1a;血管瘤…

云windows iis部署vue前端项目 步骤

工作记录 第一步 先进行vue项目打包 npm run build打包后会产生一个dist文件 然后将前端全部文件传到想要部署的windows上 这个一步直接远程连接 复制粘贴就可以 第二步 打开iis 添加网络 网站名称输入你想要用的二级域名 &#xff08;需要到**云上报备下 我这个用的是阿里…

自动化测试工具Selenium的语法续.

OK&#xff0c;那么上篇博客我们介绍了如何搭建基于Javaselenium的环境&#xff0c;并且使用selenium的一些语法给大家演示了如何进行自动化测试的案例&#xff0c;那么本篇博客我们来继续学习selenium的一些其他的比较重要的语法&#xff0c;感谢关注&#xff0c;期待三连~ 目…

快速学会创建uni-app项目并了解pages.json文件

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 前言 创建 uni-app 项目 通过 HBuilderX 创建 pages.json pages style globalStyle tabBar 前言…

从零做软件开发项目系列之二——需求调研

在接到软件开发任务之后&#xff0c;第一件要做的事情就是进行需求调研工作&#xff0c;基于前期的沟通以及合同向用户了解具体需求&#xff0c;从而有针对性地开展后续工作。整个调研过程分为调研准备&#xff0c;调研实施&#xff0c;需求分析。 1 调研准备 俗话说&#x…

基于微信小程序的宠物领养平台的设计与实现(Java+spring boot+微信小程序+MySQL)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于微信小程序的宠物领养平台的设计与实现&#xff08;Javaspring boot微信小程序MySQL&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 微信小程序 后端&#xff1a;Java…

【工程实践】使用pandas的记录

前言 工作中处理数据时&#xff0c;经常需要使用pandas&#xff0c;记录一些工作中使用pandas的习惯。 1. 合并数据 #读取原始数据 data1 pd.read_excel(/home/zhenhengdong/WORk/Classfier/Dates/Original/1.xlsx) data2 pd.read_excel(/home/zhenhengdong/WORk/Classfier/…

石油化工钻井消防vr虚拟教学实训增加学员参与感

随着石油化工企业的生产规模和数量不断扩大&#xff0c;石油化工火灾事故常有发生&#xff0c;给企业及当地居民造成难以挽回的严重损失&#xff0c;为了避免石油化工火灾安全事故发生&#xff0c;VR安全培训公司深圳华锐视点制作的石油化工火灾vr模拟应急救援系统&#xff0c;…

java+springboot+mysql小区自来水实时监控管理系统

项目介绍&#xff1a; 使用javaspringbootmysql开发的小区自来水实时监控管理系统&#xff0c;系统包含超级管理员&#xff0c;系统管理员、用户角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff1b;楼栋管理&#xff1b;租户管理、用水管理&…

远程真机测试为什么需要应用性能指标监控?

我们在使用app、小程序等手机应用的时候&#xff0c;经常会发生“卡死“等现象。”卡死“会让用户认为你的app不可信&#xff0c;从而引发删除等情况。我们辛辛苦苦、花费大量精力和费用推广的app就失败了。 因此&#xff0c;我们就需要知道&#xff0c;app在使用时候&#…

ROS_LINUX入门学习笔记=2=

B站ros机器人工匠阿杰入门教程 rqt_robot_steering 控制小乌龟 在index ros .rog中查找相关的包&#xff1a;rosindex 下图是rqt_robot_steering的简介 其中可以查看github源码地址 website可以查看效果图 下载相关的包 sudo apt install ros-kinetic-rqt-robot-steering r…

项目实战笔记2:硬技能(上)

序&#xff1a; 本节串讲了项目管理硬技能&#xff0c;有些术语可以结合书或者网上资料来理解。没有想书上讲的那样一一列举。 做计划 首先强调为什么做计划&#xff1f; 计划就是各个角色协同工作的基准&#xff08;后面做风险监控、进度的监控&#xff09;&#xff0c;贯穿于…

【华为认证】HCIA真题20道(看看HCIA的技术你掌握了多少)

正在备考华为认证的小伙伴应该知道&#xff0c;除了理论知识外&#xff0c;刷题也相当重要&#xff0c;周工这里有一份HCIAHCIP-Datacom带解析的最新题库 点赞留言 即可领取。 下图所示&#xff0c;主机A和主机B使用哪种网络设备可以实现通信&#xff1f;&#xff08; &…