[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方法来强制结束核心线程.

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

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

相关文章

DataX简介及使用

目录 一、DataX离线同步工具DataX3.0介绍 1.1、 DataX 3.0概览 1.2、特征 1.3、DataX3.0框架设计 1.4、支持的数据元 1.5、DataX3.0核心架构 1.6、DataX 3.0六大核心优势 1.6.1、可靠的数据质量监控 1.6.2、丰富的数据转换功能 1.6.3、精准的速度控制 1.6.4、强劲的…

第五十四章 安全元素的详细信息 - DerivedKeyToken 详情

文章目录 第五十四章 安全元素的详细信息 - <DerivedKeyToken> 详情详情消息中的位置 第五十四章 安全元素的详细信息 - 详情 <DerivedKeyToken> 的目的是携带发送者和接收者可以独立使用的信息来生成相同的对称密钥。这些方可以使用该对称密钥对 SOAP 消息的相关…

正则表达式和通配符

文章目录 正则表达式和通配符的区别正则表达式&#xff08;Regex&#xff09;通配符&#xff08;Wildcards&#xff09;总结 正则表达式的概念正则表达式的由来为什么要使用正则表达式 正则表达式的语法组成修饰符元字符\f\b\B 在Linux中的基础正则和扩展正则基础正则(BRE)^$.*…

人脸应用实例:性别年龄预测

在当今科技飞速发展的时代&#xff0c;人脸识别技术已经从科幻电影走进了我们的日常生活。通过算法来识别人脸的特征&#xff0c;进而判断身份、年龄和性别&#xff0c;这一技术正逐步改变着我们的生活方式。今天&#xff0c;我们就来探讨一下基于深度学习的人脸应用实例——性…

面试时被问到“Scaling Law”,该怎么答?

在大模型的研发中&#xff0c;通常会有下面一些需求&#xff1a; 计划训练一个 10B 的模型&#xff0c;想知道至少需要多大的数据&#xff1f; 收集到了 1T 的数据&#xff0c;想知道能训练一个多大的模型&#xff1f; 老板准备 1 个月后开发布会&#xff0c;给的资源是 100 …

vue父子传参的方式——Prop

Prop 每一个组件都有一个props的属性&#xff0c;用来接收外部传递的数据 这里我拿一个分页组件为例&#xff1a; 一、基础语法 1、父组件传递数据 父组件在向子组件传递数据时&#xff0c;基础语法如下&#xff1a; <template><div><common-page :pagina…

Linux安装Nginx教程(rpm安装方式)

本章教程,主要介绍如何在Linux Centos7系统上,使用rpm的方式进行安装Nginx。 一、安装wget插件 如果不存在wget下载插件,需要安装一下。 yum install -y wget二 、下载rpm安装包 官方提供的rpm下载地址:https://nginx.org/packages/centos/7/x86_64/RPMS/ <

【Nginx系列】499错误

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Java面试题——计网篇2

1.get和post请求的区别 用途不同&#xff1a; GET请求用于从服务器获取数据&#xff0c;它不会改变服务器上的数据。POST请求用于向服务器提交数据&#xff0c;通常用于修改服务器上的数据。 数据传输方式不同&#xff1a; GET请求将数据附加在URL后面&#xff0c;通过问号(?)…

Postman常见问题及解决方(全)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、网络连接问题 如果Postman无法发送请求或接收响应&#xff0c;可以尝试以下操作&#xff1a; 检查网络连接是否正常&#xff0c;包括检查网络设置、代理设置…

软考中级嵌入式系统设计师笔记分享(二)

1.TTL 电路是电流控制器件&#xff0c;而CMOS 电路是电压控制器件。 2.TTL 电路的速度快&#xff0c;传输延迟时间短(5-10ns)&#xff0c;但是功耗大。 常见的串行总线有 SPI、II2C、USB、RS232/RS422/RS485、CAN等;高速串行总线主要有 SATA、PCIE、IEEE 1394、Rapidl0、USB 3…

1.DBeaver连接hive数据库

1.hive开启远程服务&#xff0c;linux中直接输入&#xff1a;hiveserver2 2.解压dbeaver和hive-jdbc-2.1.1.zip 3.双击打开 4.数据库&#xff0c;新建连接 5.搜索hive 6.配置参数 7.编辑驱动设置 8.添加jar包 9.测试连接 10.右击&#xff0c;新建sql编辑器 11.执行sql 12.调整字…

在linux中arm-linux-gcc和/usr/bin/gcc有啥区别

在Linux中&#xff0c;arm-linux-gcc和/usr/bin/gcc都是编译器&#xff0c;但它们之间存在显著的区别&#xff0c;主要体现在编译目标、使用场景以及编译生成的二进制文件的可执行性上。而软链接则是Linux文件系统中的一种特殊文件类型&#xff0c;用于创建一个文件的别名。 a…

高级java每日一道面试题-2024年10月24日-JVM篇-说一下JVM有哪些垃圾回收器?

如果有遗漏,评论区告诉我进行补充 面试官: 说一下JVM有哪些垃圾回收器? 我回答: 1. Serial收集器 特点&#xff1a;Serial收集器是最古老、最稳定的收集器&#xff0c;它使用单个线程进行垃圾收集工作。在进行垃圾回收时&#xff0c;它会暂停所有用户线程&#xff0c;即St…

【每日一题】LeetCode - 整数转罗马数字

在罗马数字系统中&#xff0c;七个不同的符号代表不同的值&#xff1a; 符号值I1V5X10L50C100D500M1000 罗马数字的表示方式是从最大值开始逐次减去每个符号的值&#xff0c;通过组合这些符号构建最终的表示形式。本文将介绍一个基于贪心策略的解决方案&#xff0c;将整数转换…

unity开发之Line Renderer

Line Renderer 是一个有用的工具&#xff0c;可让您在游戏中绘制线条。 它可以用作游戏的函数或调试标记。 在这里&#xff0c;让我们创建一个程序&#xff0c;根据基本用法在 Line Renderer 上移动。 目录 如何使用 Line Renderer 和基础知识 在场景中放置 Line Renderer关键组…

音视频同步版本【基于音频】

其实和基于外部时钟的原理操作基本上一模一样。只不过音频帧不需要去匹配现实时钟了&#xff0c;只有视频帧需要匹配现实时钟。而视频帧需要去匹配音频帧的时间&#xff0c;那么就需要给时钟设置一个补偿&#xff0c;因为现在是以音频帧为标准。假如现在现实时钟到了50pts&…

Catalan数 C++解决

输入描述 输入一个正整数n。 输出描述 输出Catalan数的前n项。 用例输入 1 0 用例输出 1 1 用例输入 2 5 用例输出 2 1 1 2 5 14 42 #include<bits/stdc.h> using namespace std; int main() {int n;cin>>n;int dp[n1]{0};dp[0]dp[1]1;for(int m2;…

守护头顶安全——AI高空抛物监测,让悲剧不再重演

在城市的喧嚣中&#xff0c;我们享受着高楼林立带来的便捷与繁华&#xff0c;却往往忽视了那些隐藏在高空中的危险。近日&#xff0c;震惊全国的高空抛物死刑案件被最高院核准并执行。案件中被告人多次高空抛物的举动&#xff0c;夺去了无辜者的生命&#xff0c;也让自己付出了…

项目集群部署定时任务重复执行......怎么解决???

项目集群部署在不同服务器&#xff0c;导致定时任务重复执行 1、可以在部署时只让一个服务器上有定时任务模块&#xff0c;不过这样如果这台服务器宕机&#xff0c;就会导致整个定时任务崩溃 2、使用分布式锁&#xff0c;使用redis setNX命令加lua脚本在定时任务执行的时候只…