详细介绍线程池的使用原理、参数介绍、优点、常见构造方法、使用案例、模拟实现

news2024/12/27 16:50:30

前言

创建和销毁一个线程时,这点损耗是微不足道的,但是当需要频繁的创建和销毁多个线程时,这个成本是不可忽视的,于是就有大佬创建了线程池,借助线程池来减少其中的成本。

目录

前言

一、线程池的使用原理

二、线程池的参数介绍

三、使用Executors 创建常见的线程池

四、线程池的使用案例

五、线程池的模拟实现

六、线程池的优点

结语


一、线程池的使用原理

当有对象申请创建线程池时:

 所以在使用线程池的线程的时候,线程已经提前被创建好了,并且用户不使用这个线程时,这个线程会被线程池回收,等待下一次调用

二、线程池的参数介绍

有很多接口丰富的线程池类,本文这里只讲一个(讲解接口最丰富的类)

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler);

 

三、使用Executors 创建常见的线程池

Executors.newFixedThreadPool(int num);//创建一个固定线程数量的线程池
Executors.newCachedThreadPool();//创建出一个线程数目动态变化的线程池
Executors.newSingleThreadExecutor();//包含单个线程的线程池(比原生api更简单)
Executors.newScheduledThreadPool();//类似于定时器,可能由多个线程执行

都是依靠使用submit方法,将任务添加到线程中。

四、线程池的使用案例

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(4);
        service.submit(new Runnable() {
            @Override
            public void run() {
               while(true){
                   System.out.println(Thread.currentThread().getName()+111);
               }
            }
        });
        service.submit(new Runnable() {
            @Override
            public void run() {
                while(true){
                    System.out.println(Thread.currentThread().getName()+222);
                }
            }
        });

    }
}

运行截图:

 

五、线程池的模拟实现

class MyExecutor{
    private int num;//线程数量
    MyExecutor(int num){
        this.num = num;
        MyTake myTake = new MyTake();
        myTake.start();
    }

    volatile BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
    static Object object = new Object();
    class MyTake extends Thread{
        @Override
        public void run() {
            for (int i = 0; i < num; i++) {
                Thread thread = new Thread() {
                    @Override
                    public void run() {
                        synchronized (object) {
                            try {
                                //为了使线程池一直处于运行状态
                                while(true){
                                    //执行任务
                                    while (queue.isEmpty()) {
                                        object.wait();
                                    }
                                    Runnable runnable = queue.take();
                                    runnable.run();
                                }
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                };
                thread.start();
            }
        }
    }

    public void submit(Runnable runnable){
        synchronized (object){
            try {
                queue.put(runnable);
                object.notify();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

六、线程池的优点

1)降低资源消耗:减少线程的创建和销毁带来的性能开销;

2)提高响应速度:当任务来时可以直接使用,不用等待线程创建;

3)可管理性:进行统一的分配、监控,避免大量的线程之间因互相抢占系统资源导致的阻塞现象。


结语

这篇博客如果对你有帮助,给博主一个免费的点赞以示鼓励,欢迎各位🔎点赞👍评论收藏⭐,谢谢!!!

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

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

相关文章

[解决方案]Antd TreeSelect/Select placeholder失效

&#x1f50e;嘿&#xff0c;这里是慰慰&#x1f469;&#x1f3fb;‍&#x1f393;&#xff0c;会发各种类型的文章&#xff0c;智能专业&#xff0c;从事前端&#x1f43e; &#x1f389;如果有帮助的话&#xff0c;就点个赞叭&#xff0c;让我开心一下&#xff01;&#x1f…

【开个空调】语音识别+红外发射

废话少说&#xff0c;直接上空调板子&#xff1a;YAPOF3。红外接收发射模块用的某宝上发现的YF-33(遗憾解码还没搞清楚&#xff0c;不然做个lirc.conf功能才多)。最后是语音识别用的幻尔的&#xff0c;某宝自然也有&#xff0c;它是个i2c的接口。 本篇胡说八道其实纯粹为了留个…

暴力匹配或KMP算法解决字符串匹配问题

字符串匹配问题 1. 字符串匹配问题2. 解决方案2.1 暴力匹配算法2.1.1 算法步骤2.1.2 代码实现 2.2 KMP算法2.2.1 算法步骤2.2.2 next数组计算2.2.2 代码实现 3. 真题3.1 力扣 28. 找出字符串中第一个匹配项的下标3.2 力扣 459. 重复的子字符串3.3 NC149 kmp算法3.4 KMP算法 1. …

opencv进阶18-基于opencv 决策树导论

1. 什么是决策树&#xff1f; 决策树是最早的机器学习算法之一&#xff0c;起源于对人类某些决策过程 的模仿&#xff0c;属于监督学习算法。 决策树的优点是易于理解&#xff0c;有些决策树既可以做分类&#xff0c;也可以做回归。在排名前十的数据挖掘算法中有两种是决策树[1…

火山引擎发布自研视频编解码芯片

2023年8月22日&#xff0c;火山引擎视频云宣布其自研的视频编解码芯片已成功出片。经验证&#xff0c;该芯片的视频压缩效率相比行业主流硬件编码器可提升30%以上&#xff0c;未来将服务于抖音、西瓜视频等视频业务&#xff0c;并将通过火山引擎视频云开放给企业客户。 火山引…

【附安装包】Tecplot 360 EX2022安装教程

软件下载 软件&#xff1a;Tecplot 360版本&#xff1a;2022语言&#xff1a;英文大小&#xff1a;388.97M安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.5GHz 内存4G(或更高&#xff09;下载通道①百度网盘丨64位下载链接&#xff1a;https://pan.baid…

SQL注入之报错注入

文章目录 报错注入是什么&#xff1f;报错注入获取cms账号密码成功登录 报错注入是什么&#xff1f; 在注入点的判断过程中&#xff0c;发现数据库中SQL 语句的报错信息&#xff0c;会显示在页面中&#xff0c;因此可以利用报错信息进行注入。 报错注入的原理&#xff0c;就是在…

uniapp 使用permission获取录音权限

使用前&#xff0c;需要先配置权限 android.permission.RECORD_AUDIO

wazhu配置以及漏洞复现

目录 1.wazhu配置 进入官网下载 部署wazhu 修改网络适配器 重启 本地开启apache wazhu案例复现 前端页面 执行 1.wazhu配置 进入官网下载 Virtual Machine (OVA) - Installation alternatives (wazuh.com) 部署wazhu 修改网络适配器 重启 service network restart 本地…

Datawhale AI夏令营 - 用户新增预测挑战赛 | 学习笔记

数据分析与可视化 为了拟合出更好的结果就要了解训练数据之间的相互关系&#xff0c;进行数据分析是必不可少的一步 导入必要的库 # 导入库 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns pandas库是一个强大的分析结构化…

Python框架【自定义过滤器、自定义数据替换过滤器 、自定义时间过滤器、选择结构、选择练习、循环结构、循环练习、导入宏方式 】(三)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小王&#xff0c;CSDN博客博主,Python小白 &#x1f4d5;系列专栏&#xff1a;python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 &#x1f4e7;如果文章知识点有错误…

【OpenMp】openmp库的介绍及安装

目录 什么是OpenMPOpenMP的工作原理Amdahl 定律Gustafson 定律openmp的库在ubuntu下的编译 什么是OpenMP OpenMP&#xff08;Open Multi-Processing&#xff09;是一种并行编程框架&#xff0c;用于在共享内存系统中实现并行计算。它是GCC编译器的一部分&#xff0c;提供了一组…

向量检索:基于ResNet预训练模型构建以图搜图系统

1 项目背景介绍 以图搜图是一种向量检索技术&#xff0c;通过上传一张图像来搜索并找到与之相关的其他图像或相关信息。以图搜图技术提供了一种更直观、更高效的信息检索方式。这种技术应用场景和价值非常广泛&#xff0c;经常会用在商品检索及购物、动植物识别、食品识别、知…

leetcode48. 旋转图像(java)

旋转图像 题目描述旋转技巧上期经典算法 题目描述 难度 - 中等 原题链接 - 旋转图像 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像…

StreamPark

1、StreamPark的标语 一个神奇的框架&#xff0c;让流处理更简单 2、StreamPark的前世今生 早期用名streamx&#xff0c;加入apache孵化器之后更名为StreamPark 3、StreamPark可以为你提供什么 降低学习成本、开发门槛&#xff0c;让开发者只用关心核心的业务 简单来说&#xf…

Pytorch学习:torchvison.transforms常用包(ToTensor、Resize、Compose和RandomCrop)

transforms常用包 1. torchvision.transforms.ToTensor2. torchvision.transforms.Resize3. torchvision.transforms.Compose4. torchvision.transforms.Normalize5. torchvision.transforms.RandomCrop 1. torchvision.transforms.ToTensor 将PIL Image或ndarray转换为张量并…

基于React实现无限滚动的日历详细教程,附源码【手写日历教程第二篇】

前言 最常见的日历大部分都是滚动去加载更多的月份&#xff0c;而不是让用户手动点击按钮切换日历月份。滚动加载的交互方式对于用户而言是更加丝滑和舒适的&#xff0c;没有明显的操作割裂感。 那么现在需要做一个这样的无限滚动的日历&#xff0c;前端开发者应该如何去思考…

【数据结构】实现栈和队列

目录 一、栈1.栈的概念及结构&#xff08;1&#xff09;栈的概念&#xff08;2&#xff09;栈的结构 2.栈的实现&#xff08;1&#xff09;类型和函数的声明&#xff08;2&#xff09;初始化栈&#xff08;3&#xff09;销毁&#xff08;4&#xff09;入栈&#xff08;5&#x…

在 Redis 中处理键值 | Navicat

Redis 是一个键值存储系统&#xff0c;允许我们将值与键相关联起来。与关系型数据库不同的是&#xff0c; 在Redis 中&#xff0c;不需要使用数据操作语言 &#xff08;DML&#xff09; 和查询语法&#xff0c;那么我们如何进行数据的写入、读取、更新和删除操作呢&#xff1f;…

shell 11(shell重定向输入输出)

一、标准输入输出 标准输入介绍 从键盘读取用户输入的数据&#xff0c;然后再把数据拿到Shell程序中使用; 标准输出介绍 Shell程序产生的数据&#xff0c;这些数据一般都是呈现到显示器上供用户浏览查看