Java 多线程(六)—— 线程池 和 工厂模式

线程池

随着现代计算机的发展,任务越来越多,线程创建也逐渐增加,每次让操作系统创建线程这个开销就有点大,因此,我们诞生了线程池的概念,线程池里面有很多线程,这些线程可以被用户去调用执行任务,这样我们就不用每次有任务执行的时候就让操作系统创建线程了,线程池一次性就创建好好几个线程供我们使用。

为什么让操作系统创建线程还是觉得性能不够好???
CPU 有两种状态,一种是用户态,另一种是内核态,内核态就是此时 CPU 执行的是 操作系统的内核代码(操作系统是由内核和配套的应用程序构成的,操作系统的内核包含操作系统的核心功能:管理硬件设备和给程序提供稳定的运行环境),用户态就是CPU 执行除操作系统之外的代码。
如果让操作系统频繁地创建线程,此时操作系统不只是会创建线程,可能在中间还会干其他的事情,所以这里是有一定的开销的。

因此我们直接从线程池里获取线程的开销是小于让操作系统创建一个线程的开销要小的。

ThreadPoolExecutor

Java 标准库里提供了线程池的类,我们可以直接使用,这里先介绍 ThreadPoolExecutor

在这里插入图片描述

Java 在 ThreadPoolExecutor 提供了四个构造方法,这里以最长的参数的构造方法开始进行介绍,上面三个构造方法和最长的构造方法的参数含义是一致的。

在这里插入图片描述

corePoolSize 这里是核心线程数,就是这个线程池最少应该由多少线程数量。

maximunPoolSize 这是最大线程数,这个数量包括**核心线程数 加 非核心线程数,**非核心线程数可以根据具体的任务量来创建和销毁,当任务量多的时候,线程池就会创建 非核心线程来 接收这些任务,当任务量少的时候,线程池可能会把非核心的线程给销毁掉。

keepAliveTime 是存活时间,也就是这些 非核心线程 处于空余状态可以存活多久

TimeUnit unit 这个是设置时间单位的,我们在前面设置好了 keepAliveTime 之后,要搭配时间单位,这个是枚举类,时间单位如下:

在这里插入图片描述

workQueue 是阻塞队列,这个阻塞队列存放的就是任务,调用 submit 的线程就是生产者,消费这些任务的线程池里的线程就是消费者。


threadFactory 线程工厂,这个是用来统一构造和初始化线程的。工厂模式放在下面讲解

在这里插入图片描述

Java 给我们提供了ThreadFactory 接口,让我们可以自定设置创建的线程的属性,当然如果你不想这么麻烦,你就是想用用线程来处理任务,这里Java 给你提供了一个默认的工厂方法defaultThreadFactory(),这是静态方法,你直接调用就可以使用了,这个方法在import static java.util.concurrent.Executors.defaultThreadFactory;


handler 拒绝政策,当此时阻塞队列已满,但是又有线程进行了 submit 的调用,这时候 线程提供了 四种策略来应对:
在这里插入图片描述

AbortPolicy : 如果遇到阻塞队列放心不下任务的情况下会直接抛出异常 RejectedExecutionException.

CallerRunsPolicy : 是让谁调用了submit,那这个线程自己来执行 任务,举个例子:

    public static void main(String[] args) {ThreadPoolExecutor threadPoolExcutor = new ThreadPoolExecutor(10,10,10,TimeUnit.MICROSECONDS,new ArrayBlockingQueue<>(1000), defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());threadPoolExcutor.submit(() -> {System.out.println("hello");});}

如果此时队列已满,这个打印 hello 的任务就会交由调用 submit 的线程来自己执行,也就 main 线程自己执行


DiscardOldestPolicy : 是让队列抛弃最老的任务,把新的任务加入进来。

DiscardPolicy : 让队列抛弃最新的任务,也就是 submit 新传入的任务直接抛弃,老子不干了~~

工厂模式

工厂模式和之前的单例模式、阻塞队列都是一种设计模式

在Java 中我们知道方法是有重载的,但是构造方法的重载能力是有限的,例如我们有一个 类 点(Point),我们可以使用平面直角坐标系的 x 和 y 坐标进行定位并创建这个点,我们也可以使用极坐标 L 和 a 来创建点,但是这里就是两个构造方法,我们是无法进行创建,因为重载的要求 参数个数 / 参数类型不同,恰好这里的构造方法的参数个数都是两个,并且都是 double 类型:

在这里插入图片描述

为此,这里 Java 使用工厂模式来解决这个棘手的问题:通过不同的静态方法来进行对象的属性的设置。

class Point {private double x;private double y;private double l;private double a;public void setX(double x) {this.x = x;}public void setY(double y) {this.y = y;}public void setL(double l) {this.l = l;}public void setA(double a) {this.a = a;}
}
class PointFactory{public static Point PointByXY(double x, double y) {Point point = new Point();point.setX(x);point.setY(y);return point;}public static Point PointByLA(double l, double a) {Point point = new Point();point.setL(l);point.setA(a);return point;}
}

拥有工厂方法的类叫做工厂类,上面写的工厂类实现了不同构造需求的满足。

Executors

上面提到的 ThreadPoolExecutor 可能传递的参数有些麻烦,于是 Java 还给我们提供了 创建线程池的另一个类 Executors,它是对 ThreadPoolExecutor 进行了进一步的封装。

在这里插入图片描述
在这里插入图片描述


在这里插入图片描述
newFixedThreadPoll 就是创建固定线程数量的线程池,也就说核心线程数等于最大线程数


在这里插入图片描述
newWorkStealingPool 是创建一个足够大的线程池,这些线程数量能支持任务的处理,实际线程的数量是会动态的增加或者减少的。


在这里插入图片描述

这个是创建单线程的线程池,当这个线程挂掉的时候,线程池会再次创建一个新的线程来代替他继续完成工作


在这里插入图片描述

newCachedThreadPool 最大线程数可以无限大,也就是可以创建无限多的线程出来。


在这里插入图片描述

newScheduledThreadPool : 这是一个带有定时功能的线程池,也就是这个线程池会延期执行这些任务。

模拟实现

class MyThreadPoolExecutor {private BlockingQueue<Runnable> queue;private int poolSize;private Thread[] executors;public MyThreadPoolExecutor(int poolSize) {this.poolSize = poolSize;executors = new Thread[poolSize];queue = new ArrayBlockingQueue<>(1000);for (int i = 0; i < poolSize; i++) {Thread t = new Thread(() -> {while(true) {try {queue.take().run();} catch (InterruptedException e) {throw new RuntimeException(e);}}});executors[i] = t;t.start();}}public void submit(Runnable task) throws InterruptedException {queue.put(task);}
}

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

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

相关文章

Java最全面试题->Java基础面试题->JavaSE面试题->异常面试题

文章目录 异常1.说一下Java中的异常体系&#xff1f;2.Error和Exception的区别3.写出你最常见的 5 个 RuntimeException&#xff1f;4.如何处理异常?5.try()里面有⼀个return语句&#xff0c; 那么后面的finally{}里面的代码会不会被执行&#xff1f;什么时候执行&#xff0c;…

C++ 进阶:类相关特性的深入探讨

⭐在对C 中类的6个默认成员函数有了初步了解之后&#xff0c;现在我们进行对类相关特性的深入探讨&#xff01; &#x1f525;&#x1f525;&#x1f525;【C】类的默认成员函数&#xff1a;深入剖析与应用&#xff08;上&#xff09; 【C】类的默认成员函数&#xff1a;深入剖…

初阶数据结构【3】--单链表(比顺序表还好的一种数据结构!!!)

本章概述 前情回顾单链表实现单链表彩蛋时刻&#xff01;&#xff01;&#xff01; 前情回顾 咱们在上一章博客点击&#xff1a;《顺序表》的末尾&#xff0c;提出了一个问题&#xff0c;讲出了顺序表的缺点——有点浪费空间。所以&#xff0c;为了解决这个问题&#xff0c;我…

TypeScript 出现过的问题

不能将类型“unknown”分配给类型“string”。 不能直接将类型“unknown”分配给类型“string” /**** 【1 - 问题】会画红波浪线 ****/ window.document.title to?.meta?.title || /**** 【2 - 解决】解决红波浪线 ****/ const title: unknown to?.meta?.title || if …

QML 基本动画

在介绍完 QML 动画框架之后,现在我们来看看具体的动画及其用法。先从最常用的基本动画入手,这些动画包括:PropertyAnimation、ColorAnimation、Vector3dAnimation 和 PathAnimation 等,它们不仅能够帮助我们轻松地为应用程序添加动态效果,还能显著提升用户体验,使得界面更…

vue3 解决背景图与窗口留有间隙的问题

需要实现一个登录界面&#xff0c;login.vue的代码如下&#xff1a; <script> import { ref } from vue;export default {setup() {return {};}, }; </script><template><div id"login-container" class"login-container"><di…

中国古代数学的杰出研究成果之一 - 杨辉三角 - 怎么用go、C++进行编程解决

杨辉三角&#xff0c;又称帕斯卡三角形&#xff08;Pascals Triangle&#xff09;&#xff0c;是组合数学中的一个重要概念。它是一个三角形数组&#xff0c;其中每个数字是它上方左上方和右上方的数字之和。杨辉三角的每一行都代表了二项式展开式的系数&#xff0c;因此在数学…

利用 OBS 推送 WEBRTC 流到 smart rtmpd

webrtc whip 推流 & whep 拉流简介 RFC 定义 通用的 webrtc 对于 SDP 协议的交换已经有对应的 RFC 草案出炉了。这就是 WHIP( push stream ) & WHEP ( pull stream ) . WHIP RFC Link: https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html WHEP RFC Link:…

ubuntu 开启haproxy UI

一、修改haproxy.cfg nano /etc/haproxy/haproxy.cfg 添加一段 listen statsbind *:8080stats enablestats uri /uistats refresh 10sstats auth admin:123456stats admin if TRUE 重启 sudo systemctl restart haproxy 浏览器访问&#xff1a; http://192.168.31.182:80…

搜维尔科技:SenseGlove触觉反馈数据手套的用途和作用

无论是VR培训、遥控机器人、研究还是营销&#xff0c;我们的VR触觉手套都能让虚拟世界更具沉浸感和吸引力。借助我们的硬件和直观的软件开发工具&#xff0c;研究人员和开发人员可以创建真正的触觉交互。 VR培训 使用 SenseGlove进行虚拟现实训练可产生与现实训练类似的效果&a…

MySQL-CRUD-基础-(详解) ┗( ▔, ▔ )┛

目录 ❄️一、新增&#xff08;Create&#xff09;&#xff1a; ☑ 1、单行数据 全列插入&#xff1a; ☑ 2、指定列插入&#xff1a; ☑ 3、多行插入&#xff1a; ❄️二、查询&#xff08;Retrieve&#xff09;&#xff1a; ☑ 1、全列查询&#xff1a; ☑ 2、指定列查询&a…

【数据结构与算法】走进数据结构的“时间胶囊”——栈

大家好&#xff0c;我是小卡皮巴拉 文章目录 目录 引言 一.栈的基本概念 1.1 定义 1.2 特性 1.3 基本操作 二.栈的实现方式 2.1 顺序栈 2.2 链栈 三.顺序栈的实现 定义顺序栈的结构 初始化 入栈 检查栈是否为空 出栈 销毁 四.链栈的实现 定义链栈的结构 初始…

新版idea菜单栏展开与合并

新版idea把菜单栏合并了看着很是不习惯&#xff0c;找了半天原来在这里展开 ① 点击文件 -> 设置 ② 点击外观与行为 -> 外观 -> 合并主菜单和窗口标题 然后确定&#xff0c;重启即可

戴维南,叠加,稳态笔记

一点点学习笔记,仅做个人复习使用 节点电压分清电流电压源&#xff0c;电流源才能写在右边&#xff0c;容易混淆 叠加定理仅适用于线性电路&#xff0c;且不能用于计算功率&#xff0c;主要是方向&#xff0c;要看源的方向判断等效之后的&#xff0c;受控源不参与除源&#x…

数据库表的创建

运用的环境是pychram python3.11.4 创建一个表需要用到以下语法 注释已经写清楚各种语法的含义&#xff0c;记住缩进是你程序运行的关键&#xff0c;因为程序是看你的缩进来判断你的运行逻辑&#xff0c;像我这个就是缩进不合理导致的报错 那么今天分享就到这里&#xff0c;谢…

android11 usb摄像头添加多分辨率支持

部分借鉴于&#xff1a;https://blog.csdn.net/weixin_45639314/article/details/142210634 目录 一、需求介绍 二、UVC介绍 三、解析 四、补丁修改 1、预览的限制主要存在于hal层和framework层 2、添加所需要的分辨率&#xff1a; 3、hal层修改 4、frameworks 5、备…

第九届清洁能源与发电技术国际学术会议(CEPGT 2024)

第九届清洁能源与发电技术国际学术会议&#xff08;CEPGT 2024&#xff09; 2024 9th International Conference on Clean Energy and Power Generation Technology (CEPGT 2024) 【早投稿早录用&#xff0c;享受早鸟优惠】 CEPGT 2024会议已上线至IEEE官网 第九届清洁能源…

15分钟学Go 第2天:安装Go环境

第2天&#xff1a;安装Go环境 1. 引言 在学习Go语言之前&#xff0c;首先需要配置好本地开发环境。本节将详细介绍如何在Windows 11上安装和配置Go语言环境&#xff0c;包括安装步骤、环境变量设置、VS Code配置与测试、以及常见问题解决方案。完成这些步骤后&#xff0c;你将…

Java项目-基于springboot框架的基于协同过滤算法商品推荐系统项目实战(附源码+文档)

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…

Kettle9.4支持Clickhouse数据源插件开发以及性能测试

前言 最近业务这边有个指标需要用到大数据这边的列式数据库进行处理&#xff0c;由于kettle不支持clickhouse数据源驱动&#xff0c;这里查了一下网上的相关资料&#xff0c;发现了一些别人开发好的驱动包&#xff0c;下载下来后使用效果不尽人意。总结下来有以下几个问题&…