线程池的讲解和实现

news/2024/10/21 9:52:16/

🚀🚀🚀🚀🚀🚀🚀大家好,今天为大家带来线程池相关知识的讲解,并且实现一个线程池

                                    

🌸🌸🌸🌸🌸🌸🌸🌸

                                         目录

                                  🌸 1.线程池的定义

                             🌸2.线程池相关类的认识

                         🌸3.线程池的拒绝策略

                       🌸4.线程池的实现

                  🌸5.线程池的执行流程

1.线程池的定义

我们可以这样来理解

我们之前创建线程的时候一直都是向系统申请资源,虽然说线程轻量,但是频繁的创建也会消耗资源,开校是不可忽略的.因此,我们就使用线程池,用到线程的时候直接到池子里取,用完之后还给线程池就好,也就是随用随调

那么线程池有什么好处呢?

  1. 降低资源消耗:减少线程的创建和销毁带来的性能开销。
  2. 提高响应速度:当任务来时可以直接使用,不用等待线程创建
  3. 可管理性: 进行统一的分配,监控,避免大量的线程间因互相抢占系统资源导致的阻塞现象

为什么从线程池取线程要比从系统申请效率更高呢

因为从线程池取线程是纯粹的用户态操作

从系统创建线程,涉及到内核态和用户态的切换

说到这里,什么是内核态,什么是用户态台呢,我们来看一看官方的介绍

内核态:当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。其他的属于用户态。用户程序运行在用户态,操作系统运行在内核态.(操作系统内核运行在内核态,而服务器运行在用户态)。用户态不能干扰内核态.所以CPU指令就有两种,特权指令和非特权指令.不同的状态对应不同的指令。

  我们举一个现实中的例子,假如A要去银行办一张银行卡,那么

 场景:银行

滑稽老铁:你好,我想办一张银行卡

柜台人员:先生您好,请出示您的身份证复印件

滑稽老铁:啊,我忘记复印了我只带来身份证咋办

柜台人员:没关系的先生,您可以到大厅的复印机打印一张然后拿过来,或者您也可以给我我给您打印😊

滑稽老铁:哦哦,好的,那我去大厅的复印机打印

于是滑稽老铁很快打印完很快就回来了,并且很快完成了银行卡的办理

这真是一次愉悦的体验


 场景:银行

滑稽老铁:你好,我想办一张银行卡

柜台人员:先生您好,请出示您的身份证复印件

滑稽老铁:啊,我忘记复印了我只带来身份证咋办

柜台人员:没关系的先生,您可以到大厅的复印机打印一张然后拿过来,或者您也可以给我我给您打印😊

滑稽老铁:哦哦,好的,那麻烦你给我打印一下

柜台人员:好的先生,稍等

就这样,过了很久,柜台工作人员回来了,然后给滑稽老铁办好了银行卡

这真的不是愉悦的体验

因为要是让滑稽老铁自己打印,那么滑稽老铁不会墨迹,会飞快的打印完,回来办上银行卡

如果交给工作人员,他可能会先接杯水,再和别人唠会嗑啥的,会很慢

这里的滑稽老铁就是用户态,柜台里的工作人员就是内核态,滑稽老铁去大厅自己打印就是相当于线程池取线程,是纯用户态的操作而将身份证给柜台人员打印相当于向系统申请资源创建线程,涉及到内核态和用户态的切换

2.线程池相关类的知识

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** Created with IntelliJ IDEA.* Description:* User: WHY* Date: 2023-03-25* Time: 13:42*/
public class ThreadDemo1 {public static void main(String[] args) {ExecutorService pool= Executors.newFixedThreadPool(10);pool.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello");}});pool.shutdown();//线程池的销毁}}

Java标准库实现了线程池

ExcutorService直译为执行服务,也就是线程

在这个代码中我们不是通过new一个 ExcutorService创建持,而是通过调用Excutors类的静态方法来完成构造

我们把不通过构造方法,而是通过普通的静态方法来完成对象创建和构造的过程叫做工厂模式

工厂模式其实就是拿来填构造方法的坑的

当我们算一个坐标的时候,我们可以通过读横纵坐标,也可以通过极坐标的方式

来写一个伪代码

class  Point{

public Point(double x,double y)

}

public  Point(double r,double a){

}

}

我想求该点坐标,有两种方法可以完成,但是这两个方法得构成重载才行,但现在完全不符合

那么我们可以搞两个普通方法实现

public static  Point   getPointByXY(double x,double y){

//在这里new对象 new point()

//设置属性

return 

}

public static Point getPointByRA(double r,double a){

//new 对象

//设置属性

//return

}

Executors 创建线程池的几种方式
newFixedThreadPool: 创建固定线程数的线程池
newCachedThreadPool: 创建线程数目动态增长的线程池.
newSingleThreadExecutor: 创建只包含单个线程的线程池.

线程池的销毁:pool.shutdown()方法

上述的工厂类都是对ThreadPoolExecutor 类的封装.

下面我们来说一说ThreadpoolExecutor类

    • int corePoolSize:核心线程数
    • int maximumPoolSize:最大线程数=核心线程数+临时线程数
    • long keepAliveTime:临时线程保持存活的时间

      • TimeUnit unit:时间单位  s,分钟,ms
    • BlockingQueue<Runnable> workQueue:线程池要管理很多任务,这些任务放到阻塞队列里

submit方法就是把任务放到池子里

3.线程池的拒绝策略

现在来说一说线程池的拒绝策略(非常非常重要)

    • ThreadPoolExecutor.AbortPolicy

      被拒绝的任务的处理程序,抛出一个 RejectedExecutionException

      //也就是说当队列满了,再添加任务,就抛出异常,原来的任务和新增的都不干了

      • ThreadPoolExecutor.CallerRunsPolicy

        一个被拒绝的任务的处理程序,直接在 execute方法的调用线程中运行被拒绝的任务,除非执行程序已经被关闭,否则这个任务被丢弃。

        //拒绝执行新来的任务,让发布这个任务或者调用这个任务的人自己去执行,添加的线程去执行这个任务

        • ThreadPoolExecutor.DiscardOldestPolicy

          被拒绝的任务的处理程序,丢弃最旧的未处理请求,然后重试 execute ,除非执行程序关闭,在这种情况下,任务被丢弃。

          //丢弃最老任务,执行新来的任务,最老任务是指最下安排的任务,也就是阻塞队列的队首元素

          • ThreadPoolExecutor.DiscardPolicy

            被拒绝的任务的处理程序静默地丢弃被拒绝的任务。

            //不执行新的任务,丢弃最新任务

上述的ThreadPoolExecutor类的参数以及四个拒绝策略是重点!!!

4.线程池的实现

说到这里,我们已经基本清楚线程池,下面来自己实现一个线程池

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;/*** Created with IntelliJ IDEA.* Description:* User: WHY* Date: 2023-03-25* Time: 14:46*/
class MyThreadPool{//阻塞队列存放任务private BlockingQueue<Runnable> queue=new LinkedBlockingQueue<>();//将任务放到队列public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}//实现固定线程数的线程池public MyThreadPool(int n){for(int i=0;i<n;i++){Thread t=new Thread(()->{try {while(true) {Runnable runnable = queue.take();runnable.run();}} catch (InterruptedException e) {throw new RuntimeException(e);}});t.start();}}}public class ThreadingDemo2 {public static void main(String[] args) throws InterruptedException {MyThreadPool  pool=new MyThreadPool(10);for(int i=0;i<1000;i++){int number=i;pool.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello"+number);}});}}
}

5.线程池的执行策略

1.提交了任务之后,首先会对线程数和核心数进行比较,如果线程数小于核心数就直接调用去执行
2.如果线程数大于核心数了,此时新任务就会添加到阻塞队列中等待执行,当然会判断队列否为空
3.如果线程池中存活的线程已经等于核心线程数了,并且阻塞队列也满了,然后就回去判断当前线程数是否达到最大线程数了,如果没达到就创建非核心线程去执行
任务
4.如果当前线程数已经达到了最大核心数时,此时再次添加任务线程池就会执行拒绝策略

 

这就是线程池今天全部的内容了,我们今天的讲解就到这里

下期再见,886!!!


http://www.ppmy.cn/news/35977.html

相关文章

2023字节、腾讯、阿里等6家大厂Java开发面试真题+高频面试题总结

又是一年求职面试旺季&#xff0c;不管你是新进职场小白还是职场老鸟&#xff0c;这些关于java程序员面试应准备的东西你都应该知道。 面试前需要准备 1. Java 八股文&#xff1a;了解常考的题型和回答思路&#xff1b; 2. 算法&#xff1a;刷100-200 道题&#xff0c;记住刷…

Camel Quartz Component创建QuartzScheduler的过程

Camel Quartz Component创建QuartzScheduler的过程QuartzScheduler的创建通过Spring配置文件调整Quartz配置参考QuartzScheduler的创建 在QuartzComponent启动时会对QuartzScheduler进行初始化。 org.apache.camel.component.quartz.QuartzComponent#doStart 在创建QuartzSc…

什么是外盘期货?外盘期货是怎么交易的?

外盘期货是指交易所建立在中国大陆以外的期货交易&#xff0c;以美国、英国、伦敦等交易所内的产品为常见交易期货合约&#xff0c;期货合约就是指由期货交易所统一制定的、规定在将来某一特定的时间和地点交割一定数量标的&#xff0c;有些美国期货合约品种如&#xff1a;大豆…

深入理解Transformer: 从Attention到Self-Attention

当谈及深度学习中的自然语言处理&#xff08;NLP&#xff09;任务时&#xff0c;Transformer已经成为了一种极为流行的神经网络架构。其在翻译、摘要、语音识别等任务中的出色表现使得它备受关注。那么&#xff0c;究竟什么是Transformer&#xff1f;它是如何工作的&#xff1f…

《HelloGitHub》第 84 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01;简介HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。https://github.com/521xueweihan/HelloGitHub这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Pyth…

[hadoop全分布部署]Hive组件安装配置①

&#x1f468;‍&#x1f393;&#x1f468;‍&#x1f393;博主&#xff1a;发量不足 个人简介&#xff1a;耐心&#xff0c;自信来源于你强大的思想和知识基础&#xff01;&#xff01; &#x1f4d1;&#x1f4d1;本期更新内容&#xff1a;解压安装hive文件、卸载MariaDB&…

高通再度回归,然而华为、阿里已先行一步,外媒:来不及了

高通在手机芯片市场已被中国的联发科击败&#xff0c;联发科已连续3年称霸手机芯片市场&#xff0c;在手机芯片市场落败后&#xff0c;高通意图开辟新的市场&#xff0c;左想右想&#xff0c;它再度看中了服务器芯片市场&#xff0c;然而这次恐怕它已经迟了。服务器芯片市场被高…

openssl给内网IP生成ca证书(ssl证书)

一、要使用 OpenSSL 为内网 IP 生成 CA 证书&#xff0c;您需要遵循以下步骤&#xff1a; 1、创建一个存放证书的文件夹 mkdir /opt/zhengshu 注意&#xff1a;大家自己按照自己的目录创建就行&#xff0c;我的直接放在/opt目录下了。 2、生成私钥和证书请求 openssl req -…