当前位置: 首页 > news >正文

多线程(JavaEE初阶系列6)

目录

前言:

1.什么是线程池

2.标准库中的线程池

3.实现线程池

结束语:


前言:

在上一节中小编带着大家了解了一下Java标准库中的定时器的使用方式并给大家实现了一下,那么这节中小编将分享一下多线程中的线程池。给大家讲解一下什么是“池”,为什么要使用线程池。

1.什么是线程池

之前我们也有讲过“池”这个概念,我们讲过字符串常量池,数据连接池...

线程池就是提前把线程准备好,创建线程不是直接从系统中申请而是从池子中拿,当线程不用了的时候也是还给池子。它存在的目的就是为了提高效率,它最大的好处就是减少每次启动、销毁线程的损耗。线程的创建虽然比进程轻量,但是在频繁的创建的情况下,开销也是不可忽略的。

那么为什么从池子里拿比创建线程要更高效呢?

  • 从线程池拿线程,纯粹的用户态操作。
  • 从系统创建线程,涉及到用户态内核态之间的切换。真正的创建是要在内核态完成。

在上述过程中提到了用户态、内核态这两个概念,那么下来给大家解释一下什么是用户态,什么是内核态。

一个操作系统 = 内核 + 配套的应用程序

  • 其中内核就是操作系统中最核心的功能模块的集合,里面有硬件管理、各种驱动、进程管理、内存管理、文件系统...
  • 内核则需要给上层的应用程序提供支持。

比如我们执行:println("hello")这样的一个操作。

首先应用程序调用系统内核,告诉内核我要进行打印一个字符串的操作,内核再通过驱动程序,操作显示器来完成上述的请求。应用程序有很多,但是内核只有一个,内核要给这么多程序提供服务有的时候服务就不会那么及时。

举一个例子:比如银行里的工作人员和来银行办理事务的人,假设工作人员只有一个人,客户有很多,此时工作人员就相当于内核,客户就是用户。工作人员待的柜台就是用户态,银行的大厅就是用户态。如下图所示:

滑稽A此时来到柜台给工作人员说:我想办张银行卡。

此时就需要复印一些文件,这时我们有两种解决办法:

  1. A滑稽自己去大厅的复印机去复印,然后拿给工作人员。
  2. 工作人员去柜台里面的复印机去复印。

那么此时如果A滑稽自己去复印的话速度就会很快,立即复印,立即回来。但是如果是工作人员去复印的话可能就会很慢,因为柜台只有它一个人,他可能还需要给其他人提供服务。所以这也就例比于我们计算机中的用户态操作和内核态操作了,A滑稽自己复印就是用户态操作,而工作人员复印就是内核态操作。

结论:纯用户态操作,时间是可控的。涉及到内核态操作,时间就不太可控了。

2.标准库中的线程池

Java标准库中提供了线程的线程池。

ExecutorService pool = Executors.newFixedThreadPool(10);

 在这里我们可以看到和我们之前创建一个对象不太一样。

注意:这里我们使用的是工厂模式!!!

创建对象的时候不再直接new,而是使用一些其他方法(通常是静态方法)协助我们把对象创建出来。

Executors.newFixedThreadPoll()是不会设定固定值的,这里是按需创建,用完之后也不会立即销毁,留着以备后用。

下面我们来给大家演示一下:
代码展示:

package Time;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;//线程池的使用
public class ThreadDemo3 {public static void main(String[] args) {//创建一个线程池ExecutorService pool = Executors.newFixedThreadPool(10);//添加任务到线程池中pool.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello");}});}
}

结果展示:

说道这里我们就不得不去看一下Java的官方文档中对线程池的解释了。

我打开Java的官方文档,没有的同学可以点击这个链接进入☞Java Platform SE 8

进入之后点击下面的进入ThreadPoolExecutor的页面。

 我们可以看到它的参数有以下几个:

我们分别给大家解释一下:

  • corePollSize:核心线程数,如果类比一家公司的话,那么他们就是公司里面的正式员工。
  • maximumPollSize:最大线程数,相当于是公司中的正式员工+实习生。如果当前的任务比较多,线程池就会多创建一些“临时线程”。如果当前任务比较少,比较空闲了,线程池就会把多创建出来的临时线程给销毁。也就相当于在公司里面如果任务比较多的话就多招几个实习生,但是如果任务不多的话就辞退实习生,保留正式员工。
  • KeepAliveTime:线程的存活时间,如果任务不多了,那么临时创建的线程也不是一下子就销毁的,而是保留一段时间在销毁,相当于是在公司中,如果任务不多的话,实习生也不是瞬间就被辞退了,而是观察一段时间,看公司是不是长时间要处于一个不忙的状态。
  • unit:时间单位。
  • workQueue:线程池也要管理很多任务,这些任务也是通过阻塞队列来组织的,程序猿可以手动指定给线程池一个队列,此时程序猿就很方便的可以控制/获取队列中的信息了,submit方法其实就是把任务放到该队列中。
  • threadFactor:工程模式,创建线程的辅助的类。
  • handler: 线程池的拒绝策略,如果线程池的池子满了,继续往里添加任务,那么该如何进行拒绝呢?我们接着往下看。

关于线程池的拒绝策略,标准库给我们提供了四种。

下面来给大家分别解释一下:

  • ThreadPoolExecutor.AbortPolicy:表示如果任务满了,继续添加任务,添加的操作就会直接抛出异常。
  • ThreadPoolExecutor.CallerRunsPolicy:添加的线程自己负责执行这个任务。
  • ThreadPoolExecutor.DiscardOldestPolicy:丢弃最老的任务。
  • ThreadPoolExecutor.DiscardPolicy:丢弃最新的任务。

3.实现线程池

下面我们就自己来实现一个线程池。

代码展示:

package Time;import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;//自己实现的线程池
class MyThreadPool{//阻塞队列用来存放任务private BlockingDeque<Runnable> queue = new LinkedBlockingDeque<>();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) {//此处需要让线程池内部有一个while循环,不停的取任务Runnable runnable = queue.take();runnable.run();}} catch (InterruptedException e) {e.printStackTrace();}});t.start();}}
}
public class ThreadDemo4 {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);}});Thread.sleep(3000);}}
}


结果展示:

此处我们可以看到,线程池中任务的执行顺序和添加顺序不一定是相同的,这是非常正常的,因为这是个线程的调度是无序的。 

结束语:

这节小编就与大家分享到这里啦,这节中小编主要与大家分享了什么是线程池,带着大家一起看了标准库中的线程池,并且我们自己还实现了一遍,希望这节对大家线程池有一定了解,想要学习的同学记得关注小编和小编一起学习吧!如果文章中有任何错误也欢迎各位大佬及时为小编指点迷津(在此小编先谢过各位大佬啦!)

相关文章:

多线程(JavaEE初阶系列6)

目录 前言&#xff1a; 1.什么是线程池 2.标准库中的线程池 3.实现线程池 结束语&#xff1a; 前言&#xff1a; 在上一节中小编带着大家了解了一下Java标准库中的定时器的使用方式并给大家实现了一下&#xff0c;那么这节中小编将分享一下多线程中的线程池。给大家讲解一…...

shell清理redis模糊匹配的多个key

#!/bin/bash# 定义Redis服务器地址和端口 REDIS_HOST"localhost" REDIS_PORT6380# 获取匹配键的数量 function get_matching_keys() {local key_pattern"$1"redis-cli -h $REDIS_HOST -p $REDIS_PORT -n 0 KEYS "$key_pattern" }# 删除匹配的键 …...

【电网异物检测硕士论文摘抄记录】电力巡检图像中基于深度学习的异物检测方法研究

根据国家电力行业发展报告统计&#xff0c;截止到 2018 年&#xff0c;全国电网 35 千伏及以上的输电线路回路长度达到 189 万千米&#xff0c;220 千伏及以上输电线路回路长度达73 万千米。截止到 2015年&#xff0c;根据国家电网公司的统计 330 千伏及以上输电线路故障跳闸总…...

C++共享数据的保护

虽然数据隐藏保护了数据的安全性&#xff0c;但各种形式的数据共享却又不同程度地破坏了数据的安全。因此&#xff0c;对于既需要共享有需要防止改变的数据应该声明为常量。因为常量在程序运行期间不可改变&#xff0c;所以可以有效保护数据。 1.常对象 常对象&#xff1a;它…...

MyBatisPlus学习记录

MyBatisPlus(简称MP&#xff09;是基于MyBatis框架基础上开发的增强型工具&#xff0c;旨在简化开发、提高效率 MyBatisPlus简介 入门案例 创建新模块&#xff0c;选择Spring初始化&#xff0c;并配置模块相关基础信息选择当前模块需要使用的技术集&#xff08;仅选择MySQL …...

如何开启一个java微服务工程

安装idea IDEA常用配置和插件&#xff08;包括导入导出&#xff09; https://blog.csdn.net/qq_38586496/article/details/109382560安装配置maven 导入source创建项目 修改项目编码utf-8 File->Settings->Editor->File Encodings 修改项目的jdk maven import引入…...

libhv之hio_t分析

上一篇文章解析了fd是怎么与io模型关联。其中最主要的角色扮演者&#xff1a;hio_t 1. hio_t与hloop的关系 fd的值即hio_t所在loop ios变量中所在的index值。 hio_t ios[fd] struct hloop_s { ...// ios: with fd as array.index//io_array保存了和hloop关联的所有hio_t&…...

C语言的转义字符

转义字符也叫转移序列&#xff0c;包含如下&#xff1a; 转移序列 \0oo 和 \xhh 是 ASCII 码的特殊表示。 八进制数示例&#xff1a; 代码&#xff1a; #include<stdio.h> int main(void) {char beep\007;printf("%c\n",beep);return 0; }结果&#xff1a; …...

【腾讯云 Cloud Studio 实战训练营】CloudStudio体验真正的现代化开发方式,双手插兜不知道什么叫对手!

CloudStudio体验真正的现代化开发方式&#xff0c;双手插兜不知道什么叫对手&#xff01; 文章目录 CloudStudio体验真正的现代化开发方式&#xff0c;双手插兜不知道什么叫对手&#xff01;前言出现的背景一、CloudStudio 是什么&#xff1f;二、CloudStudio 的特点三、CloudS…...

Pandas时序数据分析实践—时序数据集

1. 跑步运动为例&#xff0c;对运动进行时序分析 时序数据是指时间序列数据&#xff0c;是按照时间顺序排列的数据集合&#xff0c;每个数据点都与一个特定的时间戳相关联。在跑步活动中&#xff0c;我们可以将每次跑步的数据记录作为一个时序数据样本&#xff0c;每个样本都包…...

use strict 是什么意思?使用它区别是什么?

use strict 是什么意思&#xff1f;使用它区别是什么&#xff1f; use strict 代表开启严格模式&#xff0c;这种模式下使得 JavaScript 在更严格的条件下运行&#xff0c;实行更严格解析和错误处理。 开启“严格模式”的优点&#xff1a; 消除 JavaScript 语法的一些不合理…...

常见OOM异常分析排查

常见OOM异常分析排查 Java内存溢出Java堆溢出原因解决思路总结 Java内存溢出 java堆用于存储对象实例,如果不断地创建对象,并且保证GC Root到对象之间有可达路径,垃圾回收机制就不会清理这些对象,对象数量达到最大堆的容量限制后就会产生内存溢出异常. Java堆溢出原因 无法在…...

kubernetes网络之网络策略-Network Policies

Kubernetes 中&#xff0c;Network Policy&#xff08;网络策略&#xff09;定义了一组 Pod 是否允许相互通信&#xff0c;或者与网络中的其他端点 endpoint 通信。 NetworkPolicy 对象使用标签选择Pod&#xff0c;并定义规则指定选中的Pod可以执行什么样的网络通信&#xff0…...

交换机VLAN技术和实验(eNSP)

目录 一&#xff0c;交换机的演变 1.1&#xff0c;最小网络单元 1.2&#xff0c;中继器&#xff08;物理层&#xff09; 1.3&#xff0c;集线器&#xff08;物理层&#xff09; 1.4&#xff0c;网桥&#xff08;数据链路层&#xff09; 二&#xff0c;交换机的工作行为 2.…...

8.Winform界面打包成DLL提供给其他的项目使用

背景 希望集成一个Winform的框架&#xff0c;提供权限菜单&#xff0c;根据权限出现各个Winform子系统的菜单界面。不希望把所有的界面都放放在同一个解决方案下面。用各个子系统建立不同的解决方案&#xff0c;建立代码仓库&#xff0c;进行管理。 实现方式 将Winform的UI界…...

海量数据存储组件Hbase

hdfs hbase NoSQL数据库 支持海量数据的增删改查 基于Rowkey查询效率特别高 kudu 介于hdfs和hbase之间 hbase依赖hadoopzookeeper&#xff0c;同时整合框架phoenix(擅长读写),hive&#xff08;分析数据&#xff09; k&#xff0c;v 储存结构 稀疏的&#xff08;为空的不存…...

(一)基于Spring Reactor框架响应式异步编程|道法术器

在执行程序时: 通常为了提供性能,处理器和编译器常常会对指令进行重排序。 从排序分为编译器重排序和处理器重排序两种 * (1)编译器重排序: 编译器保证不改变单线程执行结构的前提下,可以调整多线程语句执行顺序&#xff1b; * (2)处理器重排序&#xff1a; 如果不存在数据依赖…...

Vue3 让localstorage变响应式

Hook使用方式&#xff1a; import {useLocalStore} from "../js/hooks"const aauseLocalStore("aa",1) 需求一&#xff1a; 通过window.localStorage.setItem可以更改本地存储是&#xff0c;还可以更新aa的值 window.localStorage.setItem("aa&quo…...

【深度学习】InST,Inversion-Based Style Transfer with Diffusion Models,论文,风格迁移,实战

代码&#xff1a;https://github.com/zyxElsa/InST 论文&#xff1a;https://arxiv.org/abs/2211.13203 文章目录 AbstractIntroductionRelated WorkImage style transferText-to-image synthesisInversion of diffusion models MethodOverview ExperimentsComparison with Sty…...

【CSS】3D卡片效果

效果 index.html <!DOCTYPE html> <html><head><title> Document </title><link type"text/css" rel"styleSheet" href"index.css" /></head><body><div class"card"><img…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...