[JAVAEE] 多线程的案例(三) - 线程池

目录

一. 什么是线程池

二. 线程池的作用

 三. java提供的线程池类

 四. ThreadPoolExecutor的构造方法及参数理解

1. int corePoolSize: 核心线程数.

2. int maximumPoolSize: 最大线程数 = 核心线程数 + 非核心线程数

3. int keepAliveTime:非核心线程允许空闲的最大时间.

4. BlockingQueue workQueue: 工作队列.

5. ThreadFactory threadFactory: 工厂模式

6. RejectedExecutionHandle handle: 拒绝策略. (最重要)

五. 线程池的核心方法

六. 创建线程池的简化代码

七. 模拟实现线程池

八. 总结


一. 什么是线程池

线程池是一种并发处理机制, 它预先创建一定数量的线程, 并按照一定的策略管理和组织这些线程, 当有任务需要执行时, 线程池会从空闲线程中取出一个线程来执行任务, 执行完毕后, 这个线程又重新回到线程池中, 等待下一轮分配.


二. 线程池的作用

避免频繁的创建和销毁线程, 减少资源消耗.

那么我们为什么认为线程池会减少资源的消耗呢?

a.从线程池中获取线程, 通过程序代码即可实现, 是可控的.

b. 通过操作系统创建线程, 需要操作系统内核配合完成, 是不可控的.

c. 使用内核, 就需要一段代码切换到内核中, 这个过程会消耗资源.

因此, 使用线程池就可以减少应用程序切换到内核中的开销.


 三. java提供的线程池类

 

ThreadPoolExecutor类 继承 AbstractExecutototService抽象类.

AbstractExecutototService抽象类 实现 ExecutorService接口.

ExecutotService接口 拓展 Executor接口.


 四. ThreadPoolExecutor的构造方法及参数理解

面试题: 解释ThreadPoolExecutor类构造方法的参数分别是什么含义?

1. int corePoolSize: 核心线程数.

核心线程数就是线程池中的最少线程数, 线程池一创建, 核心线程也随之创建, 直到线程池销毁, 这些核心线程才销毁.

2. int maximumPoolSize: 最大线程数 = 核心线程数 + 非核心线程数

(非核心线程数是自适应的, 繁忙时创建, 不繁忙时销毁, 线程数不是越多越好)

3. int keepAliveTime:非核心线程允许空闲的最大时间.

(一旦非核心线程空闲的时间超过设定的时间, 它就会被优化).

TimeUnit unit: 时间单位. (枚举)

4. BlockingQueue<Runnable> workQueue: 工作队列.

(本质上也是生产者消费者模型, 调用submit就是在生产任务, 线程池中的线程就是在消费任务)

5. ThreadFactory threadFactory: 工厂模式

(也是一种设计模式, 用来弥补构造方法的缺陷)

在线程池中的作用: 设置线程池中的线程类型(核心线程/非核心线程)

6. RejectedExecutionHandle handle: 拒绝策略. (最重要)

为什么要使用拒绝策略: 队列满了, 调用submit添加任务使线程阻塞(没有真的阻塞), 这时就无法做别的事情的, 不是一个好的选择, 于是就需要使用拒绝策略. 使线程不阻塞.

AbortPolicy: 线程池直接抛出异常.

CallerRunsPolicy: 让调用submit的线程自己执行任务.

DiscardOldestPolicy: 丢弃最老的线程,  submit当前线程.

DiscardPolicy: 丢弃submit的这个任务.


五. 线程池的核心方法

submit(Runnable): 通过Runnable来描述一段任务, 使用submit将这段任务提交到线程池中, 线程池再分配空闲线程来执行这段任务.


六. 创建线程池的简化代码

ExecutorService executorService = Executors.newFixedThreadPool(4);

Executors.newFixedThreadPool(nThreads); // 最大线程数和核心线程数一样.(创建固定线程数目的线程池)

ExecutorService executorService = Executors.newCachedThreadPool();

最大线程数是一个很大的数字. (线程池中的线程数可以增加)


七. 模拟实现线程池

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

class MyThreadPool {
    BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(10);

    public MyThreadPool(int n) {
        // 创建固定线程数量的线程池
        // 创建n个线程
        for (int i = 0; i < n; i++) {
            Thread thread = new Thread(() -> {
                try {
                    while (true) {
                        Runnable runnable = blockingQueue.take();
                        runnable.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            thread.start();
//            System.out.println(n);
        }
    }
    public void submit(Runnable runnable) throws InterruptedException {
        blockingQueue.put(runnable);
    }
}
public class demo4 {
    static int count = 0;
    public static void main(String[] args) throws InterruptedException {
        MyThreadPool myThreadPool = new MyThreadPool(4);
        for (int i = 0; i < 100; i++) {
            myThreadPool.submit(() -> {
                System.out.println(Thread.currentThread().getName() + " count " + count);
            });
        }
    }
}

八. 总结

1. 什么是线程池. (线程池是一种并发处理机制, 它预先创建出一定数量的线程, 并使用一定的策略进行管理和组织. 当有任务需要执行时, 线程池从空闲线程出取出一个线程来执行这个任务. 执行完毕后, 这个线程又重新回到线程池中, 等待先一轮分配).

2. 线程池的作用, 避免频繁创建和销毁线程, 减少资源消耗.

(从线程池中拿取线程是应用程序级别的, 创建一个线程是操作系统内核级别的.

内核级别操作消耗的资源 > 应用程序级别消耗的资源 ==> 不可控消耗的资源 > 可控消耗的资源)

3. java提供的线程池类

4. 线程池的构造方法及参数理解. (corePoolSize, maximumPoolSize, keepAliveTime, BlockingQueue<Runnabke>, ThreadFactory, RejectedExceptionHandle)

5. 线程池的核心方法 submit(Runnable). (向线程池中提交任务, 线程池会分配空闲线程来执行).

6. 创建线程池的简化代码. (Executors.newFixedThreadPool(n) 创建具有固定线程数量的线程池

Executors.newCachedThreadPool() 创建不限制线程数量的线程池).

7. 补充: 使用shutdown方法来强制结束核心线程.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络通信与并发编程(六)线程、进程池与线程池

线程、进程池与线程池 文章目录 线程、进程池与线程池一、线程二、线程的相关操作2.1创建线程的两种方式2.2线程的其他操作2.3死锁现象和递归锁2.4条件2.5定时器2.6 队列与堆栈 三、进程池与线程池 一、线程 线程是指cpu上实际执行计算的单位&#xff0c;而进程是将计算所需资…

Leetcode刷题笔记12

HJ1 字符串最后一个单词的长度 字符串最后一个单词的长度_牛客题霸_牛客网 这里可以使用rfind()&#xff0c;rfind()函数从字符串的末尾向前查找第一个空格的位置。这个空格将是最后一个单词和前面的单词的分隔符。首先使用getline读取字符串&#xff0c;然后用rfind找到最后一…

class 36 二叉树高频题目 - 上 (不含有树形dp)

1. BFS 的两种方式 如下图, 是一个二叉树. 我们需要按照层的方式来遍历这棵树. 1.1 使用 JDK 自带的类实现(链表实现, 经典 BFS) 首先我们实现一个队列, 这个队列从头进, 从尾出.然后将根节点放入其中, 然后将放入的节点弹出,然后继续验证弹出的节点有没有左孩子, 若是有, 将…

便捷之选:微信小程序驱动的停车场管理系统

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

跨境支付,哪些国产数据库能接得住?

最近有一个非常重大的事件&#xff0c;那就是10月22日-24日的金砖国家会议。金砖国家领导人第十六次会晤是金砖国家进一步凝聚共识、以实际行动推动“全球南方”共同发展进步的重要机遇。 酝酿已久的金砖跨境支付体系&#xff0c;也在这次峰会中正式推出。金砖国家的支付系统一…

国内大语言模型哪家更好用?

大家好&#xff0c;我是袁庭新。 过去一年&#xff0c;AI大语言模型在爆发式增长&#xff0c;呈现百家争鸣之态。国内外相关厂商积极布局&#xff0c;并相继推出自家研发的智能化产品。 我在工作中已习惯借助AI来辅助完成些编码、创作、文生图等任务&#xff0c;甚至对它们产…

【计网】从零开始认识IP协议 --- 认识网络层,认识IP报头结构

从零开始认识IP协议 1 网络层协议1.1 初步认识IP协议1.2 初步理解IP地址 2 IP协议报头3 初步理解网段划分 1 网络层协议 1.1 初步认识IP协议 我们已经熟悉了传输层中的UDP和TCP协议&#xff0c;接下来我们来接触网络层的协议&#xff1a; 网络层在计算机网络中的意义主要体现…

线段树

文章目录 1 线段树概念2 线段树操作2.1 建树2.2 区间修改2.3 区间查询2.4 练习题目 3 线段树进阶3.1 乘法线段树 * 补充&#xff1a;快读快写4 End 1 线段树概念 线段树 ( S e g m e n t T r e e ) (Segment\ Tree) (Segment Tree) 是 O I OI OI 中的常用算法。线段树是一种…

PHP-FPM 性能配置优化

4 核 8 G 服务器大约可以开启 500 个 PHP-FPM&#xff0c;极限吞吐量在 580 qps &#xff08;Query Per Second 每秒查询数&#xff09;左右。 Nginx php-fpm 是怎么工作的&#xff1f; php-fpm 全称是 PHP FastCGI Process Manager 的简称&#xff0c;从名字可得知&#xff…

基于SSM的冰淇淋在线购买网站【附源码】

基于SSM的冰淇淋在线购买网站 效果如下&#xff1a; 系统首页界面 用户登录界面 冰淇淋页面 每日秒杀页面 个人中心界面 管理员登录界面 管理员功能界面 口味管理界面 冰淇淋管理界面 每日秒杀管理界面 视频教学管理界面 研究背景 近些年&#xff0c;随着中国经济发展&#…

订购 Claude AI 的第二天 它独自完成 文字转语音 flask应用

图二里&#xff0c;删除几个无关的 chats 全程我做的工作&#xff1a;向 AI 提要求&#xff0c;copy / paste 代码&#xff0c;在venv验证运行&#xff0c;向 AI 反馈&#xff0c;总共用了3个 chats.&#xff08;图中的只有一个 Chat&#xff0c; 删掉的另外两个: Python 库安…

海外云手机实现高效的海外社交媒体营销

随着全球化的深入发展&#xff0c;越来越多的中国企业走向国际市场&#xff0c;尤其是B2B外贸企业&#xff0c;海外社交媒体营销已成为其扩大市场的重要手段。在复杂多变的海外市场环境中&#xff0c;如何有效提高营销效率并降低运营风险&#xff0c;成为了众多企业的首要任务。…

计算机网络(十二) —— 高级IO

#1024程序员节 | 征文# 目录 一&#xff0c;预备 1.1 重新理解IO 1.2 五种IO模型 1.3 非阻塞IO 二&#xff0c;select 2.1 关于select 2.2 select接口参数解释 2.3 timeval结构体和fd_set类型 2.4 socket就绪条件 2.5 select基本工作流程 2.6 简单select的服务器代…

【mysql进阶】4-8 临时表空间

临时表空间 - Temporary Tablespaces 1 什么是临时表&#xff1f; ✅ 解答问题 临时表存储的是临时数据&#xff0c;不能永久的存储数据&#xff0c;⼀般在复杂的查询或计算过程中⽤来存储过渡的中间结果&#xff0c;MySQL在执⾏查询与计算的过程中会⾃动⽣成临时表&#xff0c…

C++ 抛异常

目录 一.抛异常与运行崩溃的区别 1.运行崩溃 2.抛异常 二.抛异常机制存在的意义 1.清晰的处理错误 2.结构化的错误管理 3.跨函数传递错误信息 4.异常对象多态性 三.抛异常的使用方法 1.抛出异常 (throw) 2.捕获异常 (catch) 3.标准异常类 四.抛异常的处理机制 1.抛…

2024“源鲁杯“高校网络安全技能大赛-Misc-WP

Round 1 hide_png 题目给了一张图片&#xff0c;flag就在图片上&#xff0c;不过不太明显&#xff0c;写个python脚本处理一下 from PIL import Image ​ # 打开图像并转换为RGB模式 img Image.open("./attachments.png").convert("RGB") ​ # 获取图像…

rabbitmq 使用注意事项

1&#xff0c;注意开启的端口号&#xff0c;一共四个端口号&#xff0c;1883是mqtt连接的端口号&#xff0c;如果没开&#xff0c;是连接不上的需要手动起mqtt插件。 //开始mqtt插件服务 rabbitmq-plugins enable rabbitmq_mqtt 2&#xff0c;15672端口是http网页登录的管理后…

Next Stack技术联盟成立:打造新一代基础软件技术栈

北京&#xff0c;2024 年 10 月 —— 在全球数字化浪潮的推动下&#xff0c;中国基础软件产业迎来了前所未有的创新机遇与挑战。为应对这一时代任务并推动中国基础软件的全球化进程&#xff0c;观测云携手多家领先技术企业正式宣布成立 Next Stack 技术联盟。这一联盟旨在汇聚国…

接口测试(五)jmeter——get请求

一、get请求——短信验证码&#xff08;示例仅供参考&#xff09; 1. get请求&#xff1a;传参数据直接拼接在地址后面&#xff0c;jmeter不需要设置请求头content-type 注&#xff1a;短信验证码接口&#xff0c;返回结果中不会返回短信验证码&#xff0c;是存在数据库表中&a…

Maven项目管理工具-初始+环境配置

1. Maven的概念 1.1. 什么是Maven Maven是跨平台的项目管理工具。主要服务于基于Java平台的项目构建&#xff0c;依赖管理和项目信息管理。 理想的项目构建&#xff1a;高度自动化&#xff0c;跨平台&#xff0c;可重用的组件&#xff0c;标准化的流程 maven能够自动下载依…