<JavaEE> 经典设计模式之 -- 线程池

news2024/11/18 16:37:49

目录

一、线程池的概念

二、Java 标准库中的线程池类

2.1 ThreadPoolExecutor 类

2.1.1 corePoolSize 和 maximumPoolSize

2.1.2 keepAliveTime 和 unit

2.1.3 workQueue

2.1.4 threadFactory

2.1.5 handler

2.1.6 创建一个参数自定义的线程池

2.2 Executors 类

2.3 实现自己的线程池


一、线程池的概念

1)什么是线程池?

准备预期需要使用的对象,将这些对象放入一个可以随时取用的容器中,这个容器就被称为“池”。

使用过的对象也不立刻销毁,而是放回“池”中,以备下次使用。

将线程作为上述对象,放在一个容器中,这就称为“线程池”。

2)为什么使用线程池?
在实际使用中,“线程池”并没有频繁的创建和销毁线程,而是从“池”中存取线程,这样可以减少每次启动和销毁线程的损耗,提高运行效率,减小系统开销。
3)为什么使用线程池可以提高效率?

通常创建线程,是通过向系统申请创建,需要通过系统内核完成,是具有内核态的代码。

而从线程池中存取线程,是属于用户态的代码,相比于内核态代码更可控、稳定,操作更快。


二、Java 标准库中的线程池类

2.1 ThreadPoolExecutor 类

这个类的构造方法参数众多,包含以下参数:

int corePoolSize

核心线程数

int maximumPoolSize

最大线程数

long keepAliveTime

空闲线程存活时间

TimeUnit unit

时间单位

BlockingQueue<Runnable> workQueue

任务队列

ThreadFactory threadFactory

线程工厂

RejectedExecutionHandler handler

拒绝策略

2.1.1 corePoolSize 和 maximumPoolSize

int corePoolSize 核心线程数

线程池中保持持有的最小线程数量。

int maximumPoolSize 最大线程数

线程池中可以持有的最大线程数量。
标准库提供的线程池,持有的线程数量是可以变动的,可以根据需要执行的任务数量,自适应线程的数量。

2.1.2 keepAliveTime 和 unit

long keepAliveTime 空闲线程存活时间

当线程池中的线程处于空闲状态时,会等待 keepAliveTime 时间后自动关闭。

如果keepAliveTime为0,线程在执行完任务后则不会关闭。

TimeUnit unit 时间单位
keepAliveTime 空闲线程存活时间的时间单位。

2.1.3 workQueue

BlockingQueue<Runnable> workQueue 任务队列

用于存储等待执行的任务。当线程池中的线程数量达到最大值时,新任务将被添加到队列中等待执行。

执行的任务应该是 Runnable 接口的实现类,

2.1.4 threadFactory

前置知识点:工厂模式

什么是工厂模式?

工厂模式(Factory Pattern)是一种创建型设计模式,它提供了一种在不指定具体类的情况下创建对象的接口。

工厂模式的核心思想是,将对象的创建过程抽象出来,使得使用者的创建与类的实例化过程解耦。

在工厂模式中,会实现一个工厂类,它提供一个创建对象的接口,而使用者只需要调用这个接口即可,工厂类会根据客户端的请求,返回不同类型的对象。

threadFactory 具体指什么:

ThreadFactory threadFactory 线程工厂
通过工厂类创建线程对象(简单理解就是通过这个类产出线程)。ThreadFactory 是一个接口,接口中只中有一个方法 newThread 方法,通过覆写该方法获得一个线程,同时可以给这个新线程设置一些属性。

2.1.5 handler

RejectedExecutionHandler handler 拒绝策略
线程池异常处理器,也称拒绝策略。这里的 handler 表示一个实现了 RejectedExecutionHandler 接口的实现类,传入的 handler 参数决定了出现异常时,线程池如何处理异常。
有哪几种拒绝策略,分别表示什么?
ThreadPoolExecutor.AbortPolicy当线程池满时,如果新任务无法执行,则立即抛出 RejectedExecutionException 异常,是默认策略。
ThreadPoolExecutor.CallerRunspolicy当线程池满时,如果新任务无法执行,则由调用线程自己执行新任务。
ThreadPoolExecutor.DiscardOldestPolicy当线程池满时,如果新任务无法执行,则丢弃最早添加的任务,然后执行新任务。
ThreadPoolExecutor.DiscardPolicy当线程池满时,如果新任务无法执行,则丢弃新任务,不执行。

2.1.6 创建一个参数自定义的线程池

创建并运行以下线程池和任务:

分析上述代码运行结果:

2.2 Executors 类

1)简单介绍 Executors 类
ThreadPoolExecutor 类参数较多,使用较复杂。因此,为方便使用,标准库中又提供了 Executors 类。Executors 类是对 ThreadPoolExecutor 类进行了一层封装,是一个工厂类,通过这个类创建出不同属性的线程池对象。
2)简单介绍常用的 Executors 类创建线程池的方法

newFixedThreadPool

创建固定线程数的线程池

newCachedThreadPool

创建线程数目动态增长的线程池

newSingleThreadExecutor

创建只包含单个线程的线程池

newScheduledThreadPool

创建可以定时执行任务的线程池
3)开发过程中应该使用 ThreadPoolExecutor 类还是使用 Executors 类?

ThreadPoolExecutor 类参数较多、可以自定义,这意味着使用这个类创建的线程池更灵活。

而 Executors 类相比 ThreadPoolExecutor 类多了一层封装,部分参数已经设定好,这使得 Executors 类在使用上更便利。

这两种选择,前者更偏向于高度定制化的线程池,而后者偏向于通用性。两者并无高下之分,各有偏向,使用者根据实际应用场景使用即可。

2.3 实现自己的线程池

线程池的使用有以下关键点:

<1>

线程池,肯定要有线程。在这里实现一个线程数量固定的线程池,就需要在这个类的构造方法中,根据输入的参数 n ,新建 n 个线程。
<2>维护一个阻塞队列,队列持有需要执行的任务。
<3>提供一个 submit 方法,用于将任务添加到任务队列中。
<4>线程池中的线程,也有自己的任务,就是不断地扫描任务队列,如果队列中有任务,则取出任务后执行。
<5>注意新建的线程需要有合适的启动时机。在以下实现中,我们让线程一创建就启动。

代码演示线程池的实现:

class MyThreadPool{
    //创建一个用于存放任务的队列;
    private BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(5);

    //构造方法,用于构造线程池。方法中需要将线程new出来;
    public MyThreadPool(int n){
        //设置线程需要执行的任务;
        Runnable runnable = new  Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        //从任务队列中取出任务,并执行;
                        queue.take().run();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        //循环创建线程,并启动,将线程放入队列中;
        for (int i = 0; i < n; i++){
            Thread t = new Thread(runnable);
            t.start();
        }
    }

    //添加任务方法。往任务队列中添加任务;
    public void submit(Runnable runnable) throws InterruptedException {
        queue.put(runnable);
    }
}
public class ThreadPool_Demo35 {
    public static void main(String[] args) throws InterruptedException {
        //新建线程池;
        MyThreadPool threadPool = new MyThreadPool(2);

        //给线程池添加任务;
        for (int i= 0; i < 10; i++){
            int n = i;
            threadPool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " 执行任务:" + n);
                }
            });
        }
    }
}


//运行结果:
Thread-0 执行任务:0
Thread-1 执行任务:1
Thread-0 执行任务:2
Thread-1 执行任务:3
Thread-0 执行任务:4
Thread-0 执行任务:6
Thread-0 执行任务:7
Thread-0 执行任务:8
Thread-0 执行任务:9
Thread-1 执行任务:5
...

十个任务全部成功打印。
应该注意到,线程没有执行结束,还在等待新的任务加入,这是线程池的合理功能。

阅读指针 -> 《 Synchronized 锁进阶》

链接生成中..........

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

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

相关文章

前端开发_移动Web+动画

平面转换 作用&#xff1a;为元素添加动态效果&#xff0c;一般与过渡配合使用 概念&#xff1a;改变盒子在平面内的形态&#xff08;位移、旋转、缩放、倾斜&#xff09; 平面转换又叫 2D 转换 平移 属性&#xff1a;transform: translate(X轴移动距离&#xff0c;Y轴移动…

vue2 cron表达式组件

vue2 cron表达式组件 1. 先上图 2. 代码目录 3. 直接上代码 &#xff08;组件代码太多&#xff0c;直接上压缩包&#xff0c;解压后直接用&#xff0c;压缩包再博客顶部&#xff09; 4. 使用注&#xff1a;示例代码中使用了element-ui // HomeView.vue<template><…

Python如何实现性能自动化测试

一、思考 1.什么是性能自动化测试? 性能 系统负载能力超负荷运行下的稳定性系统瓶颈 自动化测试 使用程序代替手工提升测试效率 性能自动化 使用代码模拟大批量用户让用户并发请求多页面多用户并发请求采集参数&#xff0c;统计系统负载能力生成报告 2.Python中的性能…

多任务学习(Multi-Task Learning)和迁移学习(Transfer Learning)的详细解释以及区别(系列1)

文章目录 前言一、多任务学习&#xff08;Multi-Task Learning&#xff09;是什么&#xff1f;二、多任务学习&#xff08;Multi-Task Learning&#xff09;对数据的要求三、迁移学习是什么&#xff1f;四&#xff0c;迁移学习对数据的要求五&#xff0c;多任务学习与迁移学习的…

LeetCode Hot100 22.括号生成

题目&#xff1a; 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 方法&#xff1a;灵神 组合型回溯-剪枝-枚举填左括号还是右括号 代码&#xff1a; class Solution {private int n;private char[] pat…

放弃原生SQL:Python中更优雅的数据库操作

概要 在Python中&#xff0c;通过原生SQL语句进行数据库操作是一种传统的方式&#xff0c;但现代的Python开发中&#xff0c;使用ORM&#xff08;Object-Relational Mapping&#xff09;工具和数据库连接库可以更加高效和优雅地进行增删改查操作。本文将详细介绍Python中放弃原…

Ubuntu 18.04使用Qemu和GDB搭建运行内核的环境

安装busybox 参考博客&#xff1a; 使用GDBQEMU调试Linux内核环境搭建 一文教你如何使用GDBQemu调试Linux内核 ubuntu22.04搭建qemu环境测试内核 交叉编译busybox 编译busybox出现Library m is needed, can’t exclude it (yet)的解释 S3C2440 制作最新busybox文件系统 https:…

vue,nvue,uniapp,到底是什么

vue,nvue,uniapp,到底是什么&#xff1f; 发展猜想&#xff1a; 开发移动端软件&#xff0c;一般是控件逻辑&#xff0c;可拖动控件android studio都给你设计好了。 开发web页面时&#xff0c;用vue&#xff0c;vue是前端框架。主要是终端设备通过浏览器进行访问&#xff08…

第三节JavaScript 函数、作用域、事件、字符串、运算符、比较

一、JavaScript的作用域 1、变量在函数内声明&#xff0c;变量为局部变量&#xff0c;具有局部的作用域。 局部变量&#xff1a;只能在函数内部访问 示例&#xff1a; // 此处不能调用 carName 变量 function myFunction() { var carName "Volvo"; // 函数内可…

Unirest-Java:Java发起GET、POST、PUT、DELETE、文件上传,文件下载工具类介绍

一、简介 Unirest-Java是一个轻量级的HTTP客户端库&#xff0c;用于在Java应用程序中发送HTTP请求。 它提供了简单易用的API&#xff0c;可以方便地处理GET、POST、PUT、DELETE等HTTP方法。 Unirest-Java支持异步和同步请求&#xff0c;可以轻松地与JSON、XML等数据格式进行…

MongoDB的条件操作符

本文主要介绍MongoDB的条件操作符。 目录 MongoDB条件操作符1.比较操作符2.逻辑操作符3.元素操作符4.数组操作符5.文本搜索操作符 MongoDB条件操作符 MongoDB的条件操作符主要分为比较操作符、逻辑操作符、元素操作符、数组操作符、文本搜索操作符等几种类型。 以下是这些操作…

使用医学数据集MIMIC,常见的问题记录

目录 MIMIC数据库安装及数据导入教程1.postgresql安装第一步&#xff1a;error running考虑到是不是不同的sql的冲突从报错信息出发重启之后可以安装了 2.打开navicate153.7z 不是内部或外部命令&#xff0c;也不是可运行的程序4.在postgreSQL中输入**\i xxx**命令后遇到提示pe…

idea__SpringBoot微服务06——静态资源(新依赖),首页和图标定制

静态资源 一、静态资源二、首页和图标定制————————创作不易&#xff0c;如觉不错&#xff0c;随手点赞&#xff0c;关注&#xff0c;收藏(*&#xffe3;︶&#xffe3;)&#xff0c;谢谢~~ 新依赖&#xff1a;jquery的 <dependency><groupId>org.webjars&…

阿里云SLS采集jvm日志

一、背景 java应用部署在阿里云的k8s容器里&#xff0c;采集其日志的需求则是一个不可缺少的。而不同公司的jvm日志会存在很大的差异&#xff0c;所以本文仅以我的实际情况作一个示例&#xff0c;仅供有需要采集jvm日志的同学们一个参考。 我们打印的Jvm日志格式见下&#xf…

基于JAVA+SpringBoot+Vue的前后端分离的医院信息智能化HIS系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着科技的不断发展&a…

Gson 自动生成适配器插件

在json解析方面 我们常见有下面几方面困扰 1. moshi code-gen能自动生成适配器,序列化效率比gson快,但是自定义程度不如gson,能java kotlin共存 且解决了默认值的问题 2.gson api 强大自由,但是 第一次gson的反射缓存比较慢,而且生成对象都是反射,除非主动注册com.google.gson…

maven下载安装与配置

文章目录 1. Maven下载2. 配置settings.xml2.1 指定Maven的本地仓库2.2 配置阿里云提供的镜像仓库2.3 配置 Maven 工程的基础 JDK 版本 3. 配置环境变量3.1 检查 JAVA_HOME 配置是否正确3.2 配置 MAVEN_HOME3.3 配置PATH3.4 验证 1. Maven下载 【Maven官网地址】 【Maven下载…

消息队列zookeeper集群+kafka

消息队列zookeeper集群kafka kafka 3.0之前依赖于zookpeeper zookeeper开源分布式架构&#xff0c;提供协调服务&#xff08;Apache项目&#xff09; 基于观察者模式设计的分布式服务管理架构 存储和管理数据。分布式节点的服务结束观察者的注册&#xff0c;一旦分布式节点…

在idea中使用maven创建dynamic web project

1、先创建一个empty project 2、添加一个module , 核心是选择maven archetype webapp, 这个是maven提供的创建web工程的模版。 3、添加完等自动安装好即可 4、目录可能不完整 右键src---->点击New---->点击Directory &#xff08;注意&#xff1a;这是笔者所缺失的结…

汽车4S店中的“S”指的什么?柯桥生活英语学习

很多人买车都会去4S店选购 因为比较有保障 服务又很到位 可你有没有想过 这里的“4S”是什么意思 其实&#xff0c;这几个单词大家都认识 今天我们就来聊一下 与“4S店”相关的英文表达 01 “4S店”的英语表达 其实&#xff0c;4S店的全称是&#xff1a;汽车销售服务4S店…