线程池学习(通俗易懂)

news2024/11/29 18:49:33

线程池

  • 线程池是什么
  • ThreadPoolExecutor
  • 模拟实现线程池
  • 结语

线程池是什么

假设我们要频繁的创建线程和销毁线程,但是创建线程和销毁线程是有成本的.
所以我们可以提前创建一批线程,后面需要使用的时候,直接拿就可以了,这就是线程池.
当线程不再使用的时候,就归还到池子里.

为什么从线程池里取比在系统里创建线程更加高效呢?

用系统去创建线程,需要调用系统api,进一步有系统内核完成线程的创建.
(内核是给所有线程提供服务的,这是不可控的)
如果是从线程池里取,上述在内核里的操作都已经提前做好了,取线程的过程,就变为了纯用户态(可控).

在java标准库中,也提供现成的线程池供我们使用.

public static void main(String[] args) {
        // Executors: 工厂类   newFixedThreadPool(int): 工厂方法
        // 工厂模式: 一般创建对象都是通过new来调用构造方法
        // 创建了一个固定数量的线程池
        ExecutorService service = Executors.newFixedThreadPool(4);
        // 创建一个线程树木动态变化的线程池
        //Executors.newCachedThreadPool();
        // 创建单个线程(比原本系统内核创建线程更简单)
        //Executors.newSingleThreadExecutor();
        // 创建计时器线程.可能是由多个线程共同执行所有的任务
        //Executors.newScheduledThreadPool(2);

        for (int i = 0; i < 20; i++) {
            service.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("hello Executors");
                }
            });
        }
    }

// 这里可能会用创建的全部线程去执行,打印20个hello Executors.

什么是工厂模式呢?

一般创建对象都是通过new来调用构造方法,但是构造方法的名字固定就是类名,
有的类就需要多种不同的构造方法,因为构造方法的名字固定,就只能使用方法重载来实现了.
可是还有不能使用方法重载的场景,比如数学中的一个坐标点,
可以使用笛卡尔坐标系的方式,也可以使用极坐标的方式,它们参数的个数和类型相同,无法
构成重载.
当我们使用工厂模式时,不用使用构造方法了,使用普通的方法来构造对象,这样方法的名字就可以是任意的了.由于普通方法的目的是创建对象,这样的方法一般是静态的.

ThreadPoolExecutor

除了上述的线程池之外,标准库还提供了接口更丰富的线程池类: ThreadPoolExecutor.
我么来看看java文档中ThreadPoolExecutor的构造方法,并来学习线程池构造方法的参数和含义.
在这里插入图片描述

  • int corePoolSize : 核心线程数, 在ThreadPoolExecutor里面的线程个数,并非是固定不变的,会根据当前任务的情况动态发生变化,至少得有corePoolSize 线程,哪怕线程池中一点任务也没有.
  • int maximumPoolSize: 最大线程数: maximumPoolSize表示最多的线程数,不能比这个数目更多了.
  • long keepAliveTime, TimeUnit unit : 分别表示时间和单位, 比如3000, ms, 这时就是3s.当线程超过制定时间阈值后就可以销毁了.
  • BlockingQueue workQueue: 线程中有很多任务,这些任务可以用阻塞队列来管理.
  • ThreadFactory threadFactory: 工厂模式,通过这个工厂类来创建线程.
  • RejectedExecutionHandler handler(非常重要,重点掌握): 拒绝方式/拒绝策略.我们知道,线程池中有一个阻塞队列,当阻塞队列满的时候,继续添加任务,该如何应对???
    (1) ThreadPoolExecutor.AbortPolity: 直接抛出异常,线程池就不干活了.
    (2) ThreadPoolExecutor.callerRunsPolity : 谁是添加这个新任务的线程,谁就去执行这个任务.
    (3) ThreadPoolExecutor.DiscardOldestPolity: 丢弃最早的任务,执行新的任务.
    (4) ThreadPoolExecutor.DiscardPolity: 直接把新的任务丢弃掉.

模拟实现线程池

这里我们实现一个固定数量的线程池:

class MyThreadPool {
    private final BlockingDeque<Runnable> queue = new LinkedBlockingDeque<>();
    // 添加任务
    public void submit(Runnable runnable) throws InterruptedException {
        queue.put(runnable);
    }

    // 创建一个固定数量的线程池
    public MyThreadPool(int n) {
        for (int i = 0; i < n; i++) {
            Thread thread = new Thread(() -> {
                while (true) {
                    try {
                        Runnable runnable = queue.take();
                        runnable.run();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            thread.start();
        }
    }
}
public class Demo26 {
    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("hello pool");
                }
            });
        }
    }
}

在我们创建线程池的时候,线程个数是哪来的?

  1. 有的线程的工作是"CPU密集型", 线程的工作全是运算.大部分的工作是在CPU上完成的,CPU得给它安排核心去完成工作才可以有进展.如果CPU是N个核心,当线程数量也是N的时候.这是理想情况,每个核心上一个线程.如果有很多的线程,就会阻塞等待.
  2. 有的线程是的工作,是"IO密集型", 会涉及大量的等待时间,就算线程数量多一点,也不会给CPU造成太大的负担.

在实际开发中,往往通过尝试不同的线程数,来找到合适的线程数,找到性能和系统资源开销比较均衡的数值.

结语

本篇博客总结了线程池相关的知识,满满的干货,希望有收获的小伙伴多多支持!

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

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

相关文章

软考131-上午题-【软件工程】-软件可靠性、可用性、可维护性

可靠性、可用性和可维护性是软件的质量属性&#xff0c;软件工程中&#xff0c;用 0-1 之间的数来度量。 0.66 66% 1、 可靠性 可靠性是指一个系统对于给定的时间间隔内、在给定条件下无失效运作的概率。 可以用 MTTF/ (1MTTF) 来度量&#xff0c;其中 MTTF 为平均无故障时间…

算法练习第18天|111.二叉树的最小深度

111.二叉树的最小深度 111. 二叉树的最小深度 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/minimum-depth-of-binary-tree/description/ 题目描述&#xff1a; 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最…

vue3 vueUse 连接蓝牙

目录 vueuse安装&#xff1a; useBluetooth: 调用蓝牙API 扫描周期设备 选择设备配对 连接成功 vue3的网页项目连接电脑或者手机上的蓝牙设备&#xff0c;使用vueUse库&#xff0c;可以快速检查连接蓝牙设备。 vueUse库使用参考&#xff1a; VueUse工具库 常用api-CSDN…

【代码】Python3|Requests 库怎么继承 Selenium 的 Headers (2024,Chrome)

本文使用的版本&#xff1a; Chrome 124Python 12Selenium 4.19.0 版本过旧可能会出现问题&#xff0c;但只要别差异太大&#xff0c;就可以看本文&#xff0c;因为本文对新老版本都有讲解。 文章目录 1 难点解析和具体思路2 注意事项2.1 PDF 资源获取时注意事项2.2 Capabiliti…

接口防盗刷的方法有哪些?

在工作中&#xff0c;曾经遇到过一个手机号一天发送上百次验证码得情况&#xff0c;这种明显是出问题了&#xff0c;那怎么解决和防范呢&#xff1f; 这是一个非常有意思的问题&#xff0c;防范措施挺多的。今天这篇文章专门跟大家一起聊聊&#xff0c;希望对你会有所帮助。 1…

固定测斜仪:工程观测的精密利器

在工程观测测量领域&#xff0c;固定测斜仪扮演着至关重要的角色。固定测斜仪&#xff0c;凭借其耐冲击型倾斜传感器、出色的可靠性、快速稳定的特点&#xff0c;以及简洁的安装和智能识别功能&#xff0c;已成为行业内重要工具。其输出信号为RS485数字量&#xff0c;可直接显示…

进行接口测试时,连接数据库,对数据源进行备份、还原、验证操作

进行接口测试时&#xff0c;我们需要连接到数据库中&#xff0c;对数据源进行备份、还原、验证等操作。 一、Python连接数据库常见模块 MysqlDBpython2时代最火的驱动库。基于C开发&#xff0c;对windows平台不友好。现在已经进入python3时代&#xff0c;基本不再使用MysqlCl…

OPC-UA是这样在食品和饮料中应用的

什么是 OPC-UA OPC Unified Architecture&#xff0c;即 OPC-UA&#xff0c;是一种基于 TCP/IP 的协议&#xff0c;用于自动化工程师实时、高可靠性、高效性地在控制系统级别共享数据。 OPC-UA 的特点 安全通信: OPC-UA 使用先进的加密方法和严格的访问控制&#xff0c;确保数…

基于STM32的交通灯(OLED屏显示倒计时)的Proteus仿真

文章目录 一、前言二、交通灯1.题目要求2.思路3.画图正常情况模拟故障情况 4.软件 三、总结 一、前言 最近下载了Proteus仿真软件&#xff0c;闲来无事也试试画一个简单的仿真图。 有需要软件的朋友可以去我的另外一篇博客下载和安装。 自用Proteus(8.15)仿真下载安装过程&a…

C++进阶(2)-函数

目录 一、函数提高 1.1函数默认参数 1.2函数占位参数 1.3函数重载 1.3.1函数重载概述 1.3.2函数重载注意事项 二、类和对象 2.1封装 2.1.1封装的意义 2.1.2struct和class区别 2.1.3成员属性设置为私有 2.1.4封装案例 2.2对象的初始化和清理 2.2.1构造函数和析构函数 …

数据大爆炸:WordCount程序的多元化执行方式

文章目录 主要内容1.左方工作区右键New,选择Map文件2.再创建mymap,myreducer,mywordcount类&#xff1a;3.打包在linux中运行&#xff0c;注意处理的文件式完全分布式文件3.1打jar包步骤&#xff1a; 4.完成内容 主要内容 尝试使用不同的方式运行wordcount程序。 1&#xff09…

去哪网拿去花不能提现,只能用于透支消费,那么拿去花提现是怎么实现呢?

去哪网拿去花不能提现&#xff0c;只能用于透支消费&#xff0c;那么拿去花提现是怎么实现呢&#xff1f; 申请携程拿去花之后&#xff0c;有一些人就会想着把钱提现出来拿去用。一般来说&#xff0c;他们都是通过线下门店来提现拿去花&#xff0c;拿去花允许用户先消费后付款&…

Unity类银河恶魔城学习记录13-1 p142 Save system源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili FileDataHandler.cs using System; using System.IO; using UnityEngine; p…

什么地推网推拉新副业平台最值得推荐? 赚取互联网第一桶金

随着互联网的发展&#xff0c;新型行业层出不穷。其中地推网推拉新作为互联网行业具有收入高、门槛低、时间自由等优势&#xff0c;一部分人从中嗅到了商机&#xff0c;开始纷纷接触并加入了进来。但还是有一部分人对于地推网推拉新的了解很少&#xff0c;不知道如何才能加入其…

程序设计|C语言教学——C语言基础1:C语言的引入和入门

一、程序的执行 1.定义 解释&#xff1a;借助一个程序&#xff0c;那个程序能够试图理解你的程序&#xff0c;然后按照你的要求执行。下次执行的时候还需要从零开始解释。 编译&#xff1a;借助一个程序&#xff0c;能够像翻译官一样&#xff0c;把你的程序翻译成机器语言&a…

IoC与Spring

目录 IoC控制反转 现实案例 特点 目的 DI依赖注入 小总结 介绍Spring 狭义和广义上的Spring 传统编码方式的不足 需求引入 弊端分析 IoC控制反转 现实案例 1、买水果问老板各种水果的口感而不是自己去挨个尝试一遍。 2、买房子找中介而不是自己去花时间找房东。…

字节对编码 (BPE):提升语言处理的效率和有效性

原文地址&#xff1a;byte-pair-encoding-bpe-bridging-efficiency-and-effectiveness-in-language-processing 2024 年 4 月 12 日 介绍 在快速发展的自然语言处理 (NLP) 领域&#xff0c;对人类语言高效解析和理解的追求带来了重大创新。字节对编码&#xff08;BPE&#x…

Windows 任务计划程序 【不管用户是否登录都要运行】执行时不显示CMD或程序窗口

任务计划程序右侧可以导出xml 「只在用户登录时运行」LogonType&#xff1a;InteractiveToken。 「不管用户是否登录都要运行」LogonType&#xff1a;Password。 用管理员运行CMD &#xff1a;schtasks /change /it /tn "test" 「不管用户是否登录都要运行」Logon…

邮件过滤是什么?怎么设置邮件过滤?

现在我们每天都要收发很多电子邮件。有的是朋友发来的问候&#xff0c;有的是工作伙伴的沟通&#xff0c;还有的可能是那些我们不想要的广告或垃圾邮件。这么多邮件&#xff0c;怎么看过来呀&#xff1f;其实&#xff0c;有一个好工具叫“邮件过滤”&#xff0c;它就像你的私人…

Python --- 怎么把Python当计算器用?(小白自学笔记)

怎么把Python当计算器用&#xff1f;(小白自学笔记) Part I&#xff1a;标准数学包的导入 今天刚刚装了python&#xff0c;打算用它来取代matlab的基本计算功能&#xff0c;当我的日常计算器用。(这里还有一个捷径&#xff0c;如果你跟我一样也是纯小白的话&#xff0c;直接问c…