【JavaEE初阶】多线程6(线程池\定时器)

欢迎关注个人主页:逸狼


创造不易,可以点点赞吗~

如有错误,欢迎指出~



目录

 实例3:线程池

参数解释 

核心线程数, 最大线程数

允许空闲的最大时间 ,时间单位 

任务队列(阻塞队列) 

线程工厂=>工厂设计模式 

拒绝策略 

使用举例

模拟实现一个线程池(固定线程数目的线程池)

实例4:定时器

使用举例 

定时器的模拟实现

选定数据结构 

线程安全问题

不使用sleep 


 实例3:线程池

线程池 就是把线程提前从系统中申请好,放到一个地方,后面需要使用线程的时候,直接从这个地方来取,而不是从系统中重新申请,线程用完之后,也是会还回到刚才的地方.主要是解决随着业务上对于性能要求越来越高,线程创建开销的频次越来越多的 问题,

参数解释 

核心线程数, 最大线程数

允许空闲的最大时间 ,时间单位 

任务队列(阻塞队列) 

线程工厂=>工厂设计模式 

拒绝策略 

使用举例

ThreadPoolExecutor 是封装前的 ->定制性更强,用起来更麻烦

Executors 是封装过的->定制性比较弱,用起来简单 

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class Demo30 {public static void main(String[] args) throws InterruptedException {ExecutorService service= Executors.newFixedThreadPool(4);//代表线程池中有4个线程for (int i = 0; i < 100; i++) {int id =i;//让id成为事实final,让lambda捕获service.submit(()->{Thread current = Thread.currentThread();//当前线程System.out.println("hello thread"+ id +","+ current.getName());});}//最好不要立即就终止, 可能任务还没执行完,线程就终止了Thread.sleep(2000);//把线程池里的线程都 终止掉service.shutdown();System.out.println("程序退出");}
}

加上 service.shutdown(),让前台线程强制结束

如何指定线程池中的线程个数 

模拟实现一个线程池(固定线程数目的线程池)

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;class MyThreadPool{private BlockingQueue<Runnable> queue =new ArrayBlockingQueue<>(1000);//此处n表示创建几个线程public MyThreadPool(int n){//先创建n个线程for (int i = 0; i < n; i++) {Thread t =new Thread(()->{//循环的从队列中 取任务while(true){try {Runnable runnable = queue.take();runnable.run();//执行任务} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}}//添加任务public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}
}public class Demo31_MyPool {public static void main(String[] args) throws InterruptedException {//测试代码MyThreadPool pool=new MyThreadPool(4);for (int i = 0; i < 1000; i++) {int id=i;pool.submit(()->{System.out.println("执行任务"+ id +"," + Thread.currentThread().getName());});//lambda对应的是"函数式接口", Runnable 也是同样符合这样的要求的}}
}

实例4:定时器

定时器相当于"闹钟",网络通信中,经常需要设定一个"超时时间",Java标准库中也提供了定时器实现

定时器在后端开发中特别重要和常用,和"阻塞队列" 类似,也会有专门的服务器(用来在分布式系统中 实现定时器的效果)

如果定的任务时间都是一样的值,接下来任务的执行顺序可能是串行的,也可能是并发的(取决于定时器的具体实现)

使用举例 

TimerTask本质上就是Runnable的进一步实现

import java.util.Timer;
import java.util.TimerTask;public class Demo31 {public static void main(String[] args) {Timer timer=new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello3");}},3000);//表示延时3秒钟 打印hello3timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello2");}},2000);timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello1");}},1000);System.out.println("程序开始执行");}
}

定时器的模拟实现

定时器的实现步骤:

  1. 创建类,描述一个要执行的任务(任务的内容,任务的时间)
  2. 管理多个任务,通过一定的数据结构,把多个任务存起来
  3. 有专门的线程,执行这里面的任务
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.concurrent.PriorityBlockingQueue;class MyTimerTask implements Comparable<MyTimerTask> {private Runnable runnable;// 此处这里的 time, 通过毫秒时间戳, 表示这个任务具体啥时候执行.private long time;public MyTimerTask(Runnable runnable, long delay) {this.runnable = runnable;this.time = System.currentTimeMillis() + delay;}public void run() {runnable.run();}public long getTime() {return time;}@Overridepublic int compareTo(MyTimerTask o) {// 此处这里的 - 的顺序, 就决定了这里是大堆还是小堆.// 此处需要小堆.// 这里是谁减谁, 不要背. 可以先写成一种顺序, 试试.return (int) (this.time - o.time);// return (int) (o.time - this.time);}
}class MyTimer {private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();private Object locker = new Object();public MyTimer() {// 创建线程, 负责执行上述队列中的内容Thread t = new Thread(() -> {try {while (true) {synchronized (locker) {while (queue.isEmpty()) {locker.wait();}MyTimerTask current = queue.peek();// 比如, 当前时间是 10:30, 任务时间是 12:00, 不应该执行.// 如果当前时间是 10:30, 任务时间是 10:29, 应该执行if (System.currentTimeMillis() >= current.getTime()) {// 要执行任务current.run();// 把执行过的任务, 从队列中删除.queue.poll();} else {// 先不执行任务locker.wait(current.getTime() - System.currentTimeMillis());// Thread.sleep(current.getTime() - System.currentTimeMillis());}}}} catch (InterruptedException e) {throw new RuntimeException(e);}});t.start();}public void schedule(Runnable runnable, long delay) {synchronized (locker) {MyTimerTask myTimerTask = new MyTimerTask(runnable, delay);queue.offer(myTimerTask);locker.notify();}}
}

选定数据结构 

按照时间来执行任务,只要能够确定所有任务中时间最小的任务,判定其是否到达执行时间即可(其他时间的任务必定排在 时间最小任务后面),所以使用优先级队列是最好的选择

为啥不使用BlockingQueue阻塞队列作为实现定时器的数据结构?

  • 阻塞队列里的take里也有一把锁,容易出现死锁情况
  • 代码的复杂程度会增加

对于所有的修改操作都要加上锁

线程安全问题

通过对进队列和出队列进行加锁

使用wait操作,避免出现 "线程饿死" 这种情况

不使用sleep 

为啥使用wait,不使用sleep让线程阻塞?

业界实现定时器除了基于优先级队列的方式之外,还有一种典型的实现方式,"时间轮"(也是一种巧妙设计的数据结构)

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

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

相关文章

leetcode:最高乘法得分

用auto可以过 class Solution { public:long long maxScore(vector<int>& a, vector<int>& b) {int n b.size();vector<vector<long long>> memo(4,vector<long long>(b.size(), LLONG_MIN));auto dfs [&](auto&& dfs, i…

构建自己的文生图工具:Python + Stable Diffusion + CUDA

构建自己的文生图工具&#xff1a;Python Stable Diffusion CUDA 前言概述环境搭建安装PyTorch安装Stable Diffusion编写Python代码结论结语 前言 在这个数字化和人工智能飞速发展的时代&#xff0c;图像生成技术正逐渐成为现实。想象一下&#xff0c;只需输入几个关键词&…

Nginx反向代理出现502 Bad Gateway问题的解决方案

&#x1f389; 前言 前一阵子写了一篇“关于解决调用百度翻译API问题”的博客&#xff0c;近日在调用其他API时又遇到一些棘手的问题&#xff0c;于是写下这篇博客作为记录。 &#x1f389; 问题描述 在代理的遇到过很多错误码&#xff0c;其中出现频率最高的就是502&#x…

【数据结构与算法 | 灵神题单 | 自顶向下DFS篇】力扣1022,623

1. 力扣1022&#xff1a;从根到叶的二进制之和 1.1 题目&#xff1a; 给出一棵二叉树&#xff0c;其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。 例如&#xff0c;如果路径为 0 -> 1 -> 1 -> 0 -> 1&#xff0c;那…

OpenHarmony(鸿蒙南向开发)——标准系统方案之扬帆移植案例

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——轻量系统STM32F407芯片移植案…

SpringBoot---------Actuator监控

1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> </dependency> 2、开启配置 management.endpoints.web.exposure.include* 3、启动项目&#xff0c;查看监控…

Linux·权限与工具-git与gdb

1. git工具 git是一款软件&#xff0c;发明它的人同时发明了Linux操作系统&#xff0c;也就是大名鼎鼎的Linus Torvalds 林纳斯托瓦兹。后来人们把git软件包装&#xff0c;产生了github、gitee等平台。 git产生的初衷就是便于进行多人协同管理&#xff0c;同时它还可以用来将本…

神经网络通俗理解学习笔记(3)注意力神经网络

Tansformer 什么是注意力机制注意力的计算键值对注意力和多头注意力自注意力机制注意力池化及代码实现Transformer模型Transformer代码实现BERT 模型GPT 系列模型GPT-1模型思想GPT-2模型思想GPT-3 模型思想 T5模型ViT模型Swin Transformer模型GPT模型代码实现 什么是注意力机制…

Linux基础开发环境(git的使用)

1.账号注册 git 只是一个工具&#xff0c;要想实现便捷的代码管理&#xff0c;就需要借助第三方平台进行操作&#xff0c;当然第三平台也是基于git 开发的 github 与 gitee 代码托管平台有很多&#xff0c;这里我们首选 Github &#xff0c;理由很简单&#xff0c;全球开发者…

Redis - 深入理解Redis事务

目录 Redis是如何实现事务的&#xff1f;事务中执行的命令出现错误&#xff0c;会回滚事务吗&#xff1f;同一个连接可以重复开启事务吗&#xff1f;多个客户端同时开启事务会怎样&#xff1f;使用Redis事务只用MULTI和EXEC吗&#xff1f;Redis中的WATCH机制是怎么实现的&#…

UDP聊天室项目

代码思路 服务器 #include <stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h>…

JVM 调优篇7 调优案例1-堆空间的优化解决

一 jvm优化 1.1 优化实施步骤* 1)减少使用全局变量和大对象&#xff1b; 2)调整新生代的大小到最合适&#xff1b; 3)设置老年代的大小为最合适&#xff1b; 4)选择合适的GC收集器&#xff1b; 1.2 关于GC优化原则 多数的Java应用不需要在服务器上进行GC优化&#xff1…

ESP8266做httpServer提示Header fields are too long for server to interpret

CONFIG_HTTP_BUF_SIZE512 CONFIG_HTTPD_MAX_REQ_HDR_LEN1024 CONFIG_HTTPD_MAX_URI_LEN512CONFIG_HTTPD_MAX_REQ_HDR_LEN由512改为1024

02 基于STM32的按键控制继电器驱动电机

本专栏所有源资料都免费获取&#xff0c;没有任何隐形消费。 注意事项&#xff1a;STM32仿真会存在各种各样BUG&#xff0c;且尽量按照同样仿真版本使用。本专栏所有的仿真都采用PROTEUS8.15。 本文已经配置好STM32F103C8T6系列&#xff0c;在PROTUES仿真里&#xff0c;32单片…

Games101图形学笔记——着色

Shading Z-buffering&#xff08;深度缓冲&#xff09; Shading&#xff08;着色&#xff09;画家算法Z-BufferShading(着色&#xff09;Blinn-Phong Reflectance Model&#xff08;布林冯反射模型&#xff09;漫反射能量守恒 着色高光Blinn-Phong Reflection ModelShadingFreq…

webGL 综合教程100+【目录】

webGL 综合教程100旨在为开发者提供两大方面的知识信息&#xff1a;&#xff08;1&#xff09;提供详细的每个api知识点的详解 &#xff08;2&#xff09;提供实战的示例&#xff0c;提供源代码。 在这量大系统性的知识下&#xff0c;给用户提供清晰的思路和示例参考&#xff0…

IEEE-754 32位十六进制数 转换为十进制浮点数

要将 IEEE-754 32位十六进制数 转换为 十进制浮点数&#xff0c;可以使用LabVIEW中的 Type Cast 函数。以下是一些具体步骤&#xff0c;以及相关实例的整理&#xff1a; 实现步骤&#xff1a; 输入十六进制数&#xff1a;在LabVIEW中&#xff0c;首先需要创建一个输入控制器&am…

传输层协议——udp/tcp

目录 再谈端口号 udp 协议 理解报头 udp特点 缓冲区 udp使用的注意事项 tcp协议 TCP的可靠性与提高效率的策略 序号/确认序号 窗口大小 ACK&#xff1a; PSH URG RST 保活机制 重传 三次握手(SYN) 四次挥手(FIN) 流量控制 滑动窗口 拥塞控制 延迟应答 捎带应答 面…

GPT撰写开题报告教程——课题确定及文献调研

撰写开题报告是一项复杂而重要的任务&#xff0c;需要涵盖从主题选择到文献综述、研究方法等多个环节。借助AI&#xff0c;如ChatGPT&#xff0c;可以显著提高这一过程的效率以及内容的质量。本文将详细探讨如何一步步利用ChatGPT撰写开题报告。 一、开题报告内容 一个清晰的…

[数据集][目标检测]智慧养殖场肉鸡健康状态检测数据集VOC+YOLO格式4657张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;4657 标注数量(xml文件个数)&#xff1a;4657 标注数量(txt文件个数)&#xff1a;4657 标注…