了解线程池

news2024/12/22 23:30:21

引出线程池:

假设小编是一个女生,小编处了一个对象,但是某一天小编不想和这个男生处对象了,但是小编还是想和别的男生处对象的,于是现在我就面临两个问题:一、怎么跟现任分手  二、开始物色新的对象,培养感情,这两个操作都非常耗时。那怎么可以提高效率一点呢?如果我既跟现任谈恋爱,又同时和其他的小哥哥暧mei,这样再我跟现任分手的同一时刻,就可以和其他的小哥哥在一起,如果这样的小哥哥多的话,就构成了一个“备胎池”。(上述纯属虚构,不适用于生活)

线程池最大的好处就是可以减小开启、销毁线程的损耗。

标准库中的线程池

标准库提供了类,ThreadPoolExecutor(构造方法,参数有很多)

这里主要讲解上图中的第四个构造方法

  • corePoolSize : 线程池中最基本的线程数量(类似于公司的正式员工,一旦录用,不辞退)
  • maximumPoolSize : 线程池中最大的线程数量(正式员工 + 临时员工,临时员工,一段时间不干活,会被辞退)
  • keepAliveTime : 运行空闲时间(临时员工,允许空间的时间,一旦时间达到就会被辞退)
  • unit :keepAliveTime 的时间单位,是秒,分钟,还是其他值
  • workQueue:传递任务的阻塞队列
  • threadFactory:创建线程的工厂,参与具体的创建线程工作。通过不同线程工厂创建出来的线程相当于对一些属性进行了不同的初始化设置。
  • RejectedExecutionHandler:拒绝策略,如果任务量超出负荷接下来怎么处理

              🍉. AbortPolicy():超过符合,直接抛出异常。

              🍉. CallerRunsPolicy():调用者负责处理多出来的任务

              🍉. DiscardOldestPolicy():丢弃队列中最老的任务

              🍉. DiscardPolicy:丢弃新来的任务

小结:在 Java 标准库线程池中,把池中的线程分为两类

1)核心线程数量(线程池中最少的线程数量)

2)非核心线程数量(线程扩容过程中,新增的)

最大线程数 = 核心线程数 + 非核心线程数

❗:非核心线程数的创建是在 核心线程已全部跑起来,并且此时阻塞队列(workQueue)也被占满,此时会创建非核心线程。

实现线程池

Java标准库中实现 线程池 的用法,这里就不写了,本次主要是实现自己自定义的线程。

  • 使用 MyBlockingQueue 组织所有的任务
  • 使用 MyThreadPoolExecutor 来创建线程池

🍉 创建阻塞队列

class MyBlockingQueue {
    public static Runnable[] arr=null;
    public static volatile int date=0;//指向队列尾
    public static volatile int head=0;//指向队列头
    public static volatile int size=0;//队列长度设置

    public static Object locker=new Object();

    public MyBlockingQueue(int capacity) {
        arr=new Runnable[capacity];
    }
    public void put(Runnable x) throws InterruptedException {
        synchronized (locker){
            while(size==arr.length){
                locker.wait();
            }
            arr[date++]=x;
            size++;
            if(date>=arr.length){
                date=0;//如果达到了队尾,指向队首
            }
            locker.notify();
        }

    }
    public Runnable take() throws InterruptedException {
        Runnable ret=null;
        synchronized (locker){
            while(size==0){
                locker.wait();
            }
            ret=arr[head++];
            size--;
            if(head>=arr.length){
                head=0;
            }
            locker.notify();
        }
        return ret;
    }
    public int getsize(){
        return size;
    }
}

 🍉 使用 MyThreadPoolExecutor 来创建线程池

class MyThreadPoolExecutor{
   private MyBlockingQueue queue=new MyBlockingQueue(10);
  private Thread[] threads=null;
  private volatile boolean isQuit=false;

    public MyThreadPoolExecutor(int capacity) {
        threads=new Thread[capacity];
        //根据capacity的值来创建线程的个数
        for (int i = 0; i < capacity; i++) {
            threads[i]=new Thread(()->{
                //每个线程不停的从队列中获取任务
                while(!isQuit){
                    try {
                        Runnable run = queue.take();
                        run.run();
                    } catch (InterruptedException e) {
                        // 线程被中断,退出循环
                        break;
                    }
                }
            });
            threads[i].start();
        }
    }

    //递交方法
    public void submit(Runnable run){
        try {
            queue.put(run);//任务在这里被接受
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    // 停止所有的 worker线程 这个只在线程池要关闭的时候才会调用
    private void stopAllThread() {
        for (Thread worker : threads) {
            worker.stop(); // 调用 worker 的 stop 方法 让正在执行 worker 当中 run 方法的线程停止执行
        }
    }

    public void shutDown() {
        // 等待任务队列当中的任务执行完成
        while (queue.getsize() != 0) {
            // 如果队列当中还有任务 则让出 CPU 的使用权
            Thread.yield();
        }
        // 在所有的任务都被执行完成之后 停止所有线程的执行
        stopAllThread();
    }

}

     注意上述使线程池中线程停止执行的方法( shutDown() 方法 )的抒写~~ 

   🍉 代码汇总

//创建线程池
class MyThreadPoolExecutor{
   private MyBlockingQueue queue=new MyBlockingQueue(10);
  private Thread[] threads=null;
  private volatile boolean isQuit=false;

    public MyThreadPoolExecutor(int capacity) {
        threads=new Thread[capacity];
        //根据capacity的值来创建线程的个数
        for (int i = 0; i < capacity; i++) {
            threads[i]=new Thread(()->{
                //每个线程不停的从队列中获取任务
                while(!isQuit){
                    try {
                        Runnable run = queue.take();
                        run.run();
                    } catch (InterruptedException e) {
                        // 线程被中断,退出循环
                        break;
                    }
                }
            });
            threads[i].start();
        }
    }

    //递交方法
    public void submit(Runnable run){
        try {
            queue.put(run);//任务在这里被接受
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    // 停止所有的 worker线程 这个只在线程池要关闭的时候才会调用
    private void stopAllThread() {
        for (Thread worker : threads) {
            worker.stop(); // 调用 worker 的 stop 方法 让正在执行 worker 当中 run 方法的线程停止执行
        }
    }

    public void shutDown() {
        // 等待任务队列当中的任务执行完成
        while (queue.getsize() != 0) {
            // 如果队列当中还有任务 则让出 CPU 的使用权
            Thread.yield();
        }
        // 在所有的任务都被执行完成之后 停止所有线程的执行
        stopAllThread();
    }

}

//阻塞队列使用数组来实现
class MyBlockingQueue {
    public static Runnable[] arr=null;
    public static volatile int date=0;//指向队列尾
    public static volatile int head=0;//指向队列头
    public static volatile int size=0;//队列长度设置

    public static Object locker=new Object();

    public MyBlockingQueue(int capacity) {
        arr=new Runnable[capacity];
    }
    public void put(Runnable x) throws InterruptedException {
        synchronized (locker){
            while(size==arr.length){
                locker.wait();
            }
            arr[date++]=x;
            size++;
            if(date>=arr.length){
                date=0;//如果达到了队尾,指向队首
            }
            locker.notify();
        }

    }
    public Runnable take() throws InterruptedException {
        Runnable ret=null;
        synchronized (locker){
            while(size==0){
                locker.wait();
            }
            ret=arr[head++];
            size--;
            if(head>=arr.length){
                head=0;
            }
            locker.notify();
        }
        return ret;
    }
    public int getsize(){
        return size;
    }
}

//入口点
public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPoolExecutor pool=new MyThreadPoolExecutor(4);
        for (int i = 0; i < 1000; i++) {
            int id=i;
            //传递的一个一个的任务
            pool.submit(()->{
                System.out.println(Thread.currentThread().getName() +"执行了"+ id);

            });
        }
            pool.shutDown();
    }
}

上述代码,核心操作为 submit 将任务加入到线程池中。

🚩文化篇:若汝志在辉煌,山不加阻,海不设限。

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

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

相关文章

软件安装攻略:Sublime Text 下载安装和使用教程

Sublime Text 下载安装和使用教程 Sublime Text是一个流行的跨平台文本编辑器&#xff0c;它具有以下一些主要功能和特点&#xff1a; &#xff08;1&#xff09;简洁的界面和快速的速度&#xff1a;Sublime Text拥有简约干净的界面&#xff0c;启动和响应速度很快。 &#…

Visual Studio打开项目的一些小技巧

Visual Studio(VS)是一款功能强大的集成开发环境&#xff0c;许多刚入门C/C的小白也会使用这款软件进行写代码&#xff0c;然而它的操作并不简单&#xff0c;下面将讲解一下VS打开项目文件的一些小技巧。 目录 &#x1f381;创建空项目 ❤️①点击“创建新项目” ❤️②点击“…

Unity中InputField一些属性的理解

先看代码&#xff1a; using UnityEngine; using UnityEngine.UI;public class TestInput : MonoBehaviour {[SerializeField]InputField inputField;void Start(){Debug.Log(inputField.text);Debug.Log(inputField.text.Length);Debug.Log(inputField.preferredWidth);Debug…

Netty笔记02-组件EventLoop

文章目录 EventLoop概述EventLoop 的概念EventLoop 的作用EventLoop 的生命周期EventLoopGroupEventLoop 的工作原理总结 代码示例&#x1f4a1; 优雅关闭演示 NioEventLoop 处理 io 事件解决work中的channel读操作耗费时间过长&#xff0c;影响其他channel(客户端)的问题&…

开源链动 2+1 模式 AI 智能名片与 S2B2C 商城小程序在用户运营中的应用

摘要&#xff1a; 本文深入探讨了用户运营中不同用户阶段的特点及策略&#xff0c;引入“开源链动 21 模式 AI 智能名片 S2B2C 商城小程序”&#xff0c;分析其在用户运营各个阶段的作用和价值&#xff0c;旨在为企业提供更高效的用户运营方案&#xff0c;实现用户价值的最大化…

Spring 框架——@Async 注解

目录 1.同步调用与异步调用1.1.同步调用1.2.异步调用1.3.总结 2.注解 Async 介绍2.1.用在方法上2.2.用在类上 3.使用演示3.1.在启动类或者配置类上增加 EnableAsync 注解3.2.在异步方法上增加 Async 注解3.3.调用异步方法3.4.测试3.5.其它说明 4.注意事项4.1.Async 注解失效的常…

【Qt绘图】—— 运用Qt进行绘图

目录 &#xff08;一&#xff09;基本概念 &#xff08;二&#xff09;绘制各种形状 2.1 绘制线段 2.2 绘制矩形 2.3 绘制圆形 2.4 绘制文本 2.5 设置画笔 2.6 设置画刷 &#xff08;三&#xff09;绘制图片 3.1 绘制简单图片 3.2 平移图片 3.3 缩放图片 3.4…

Linux 手动安装Ollama

Linux 离线安装Ollama 前言 不知道为什么 在阿里云服务器上 执行curl -fsSL https://ollama.com/install.sh | sh一键安装 非常慢 所以只能手动装了 1.到 https://ollama.com/install.sh 下载安装执行文件 修改其中 下载和安装部分代码 if curl -I --silent --fail --location…

Python数据分析-Numpy快速入门

一、什么是Numpy 二、 创建 Numpy ndarray对象 三、数组中的维度 1.各种维度数组 2.检查维度数 3.创建更高维度的数组 四、数组索引 1.访问数组元素 2.访问2-D数组元素 其他维度的同理 3.负索引 五、数据裁剪&#xff1a;要头不要尾 1.裁剪数组 demo&#xff1a; 2.负裁…

构建基于 Feign 的微服务:从 Eureka 到负载均衡的实践 --day05

目录 步骤1&#xff1a;创建父工程feign-1步骤2&#xff1a;改造服务提供者使用 RequestMapping使用 GetMapping 步骤3&#xff1a;改造服务消费者为Feign客户端&#xff08;1&#xff09;添加Feign依赖&#xff08;2&#xff09;添加EnableFeignClients注解&#xff08;3&…

YoloV10 训练自己的数据集(推理,转化,C#部署)

目录 一、下载 三、开始训练 train.py detect.py export.py 超参数都在这个路径下 四、C#读取yolov10模型进行部署推理 如下程序是用来配置openvino 配置好引用后就可以生成dll了 再创建一个控件&#xff0c;作为显示 net framework 4.8版本的 再nuget工具箱里下载 …

thinkphp6开发的通用网站系统源码

thinkphp6开发的通用网站系统源码。 基于ThinkPHP6框架开发的通用后台权限管理系统&#xff0c;底层采用国内最流行的ThinkPHP6框架&#xff0c; 支持内容管理、文章管理、用户管理、权限管理、角色管理等功能。 代码下载

Cookie和Session的对比

Cookie和Sesion 一、cookie和session创建对象 2024/9/15 10:23:59 你想了解的是如何在某种编程语言中创建和管理 cookies 和 sessions 吗&#xff1f;如果是的话&#xff0c;具体是哪个语言或框架呢&#xff1f; 2024/9/15 10:24:09 二、创建对象是客户端还是服务器 2024/…

20Kg载重30分钟续航多旋翼无人机技术详解

一、机架与结构设计 1. 材料选择&#xff1a;为了确保无人机能够承载20Kg的负载&#xff0c;同时实现30分钟的续航&#xff0c;其机架材料需选用轻质高强度的材料&#xff0c;如碳纤维或铝合金。这些材料不仅具有良好的承重能力&#xff0c;还能有效减轻无人机的整体重量&…

一步一步搭建AI智能体应用

您可以在百炼控制台以零代码的方式快速创建智能体应用&#xff0c;并将RAG&#xff08;Retrieval-Augmented Generation&#xff0c;检索增强生成&#xff09;以及插件能力集成进来。应用创建完成后&#xff0c;您可以通过控制台或API的方式来使用。 以下均以 大模型应用指代 智…

微信小程序使用 ==== 粘性布局

目录 Chrome杀了个回马枪 position:sticky简介 你可能不知道的position:sticky 深入理解粘性定位的计算规则 粘性定位其他特征 代码实现 微信小程序在scroll-view中使用sticky Chrome杀了个回马枪 position:sticky早有耳闻也有所了解&#xff0c;后来&#xff0c;Chro…

通过API接口获取下来的数据需要怎样应用?

在当今数字化时代&#xff0c;通过API接口获取数据已成为企业获取、处理和分析信息的重要手段。API接口不仅能够提高数据交互的效率&#xff0c;还能促进数据的安全性和灵活性。以下是如何将通过API接口获取的数据有效应用的一些方法和策略。 数据整合与分析 企业可以通过API接…

QPS和TPS的区别简单理解

QPS&#xff08;Queries Per Second&#xff09; QPS是指每秒查询率&#xff0c;它是衡量服务器处理能力的一个指标&#xff0c;表示服务器在一秒钟内能够响应的查询次数。这个指标通常用于数据库或服务器的性能测试&#xff0c;反映了服务器在规定时间内处理流量的能力。QPS …

浮动元素详解

浮动元素 代码实现&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title>浮动元素</title><style>#container1 {width: 400px;height: 50px;background-color: lightgrey;border: 1px solid;}#contai…

世界杯足球赛网站---附源码73185

摘 要 随着互联网的普及和足球运动的全球性影响力&#xff0c;建立一个专门的世界杯足球赛网站成为了与球迷互动和传播赛事信息的重要途径。本论文聚焦于世界杯足球赛网站的设计与实现&#xff0c;旨在探讨如何利用现代技术为球迷提供一个全方位的足球赛事体验。 通过对 Spring…