Java高并发系列: 使用wait - notify实现高效异步方法
1. 背景
在项目开发中, 通常会有异步执行操作, 例如: 提交一个异步清空一系列数据库中ID = ${_id} 的记录, 这个时候通常的做法是主线程将任务添加到一个异步队列中, 后台维护一个线程不断地循环扫描这个队列, 如果有需要执行的任务, 则执行相应的逻辑. 如下图所示:
2. 一个简单的异步执行方法
代码实现如下所示:
public class AsyncExecutor {private static final Deque<AsyncTaskEntity> taskQueue = new ConcurrentLinkedDeque<>();public AsyncExecutor() {Thread thread = new Thread(() -> {while (true) {try {if (taskQueue.isEmpty()) {// 休眠50毫秒ThreadUtil.sleep(50);continue;}AsyncTaskEntity entity = taskQueue.pollFirst();execute(entity);} catch (Exception e) {LOGGER.error("异步执行任务出现异常!", e);}}});thread.setName("异步任务执行器");thread.start();System.out.println("analysis异步队列任务启动完成!");}public static <T> void asyncExecute(AsyncTaskEntity<T> entity) {taskQueue.push(entity);}
}/*** 队列中任务对象封装*/
@Data
public class AsyncTaskEntity <T>{// 消费的参数private T param;public AsyncTaskEntity(T param){this.param = param;}
}
有了上面的异步执行器之后, 这里我们写一个main方法, 在main方法中通过异步的方式执行一些任务:
public class Main{public static AsyncExecutor asyncExecutor = new AsyncExecutor();public static void main(String[] args) throws Exception;{for(int i = 0;i<10;i++){asyncExecutor.asyncExecute(new AsyncTaskEntity<Integer>(i));}Thread.sleep(10_000);}
}
到此为止一个简单清晰的异步调用逻辑就已经写完了. 但是现在不得不考虑一个事情, 异步线程中while(true)
会一直空转, 即使没有任务。因此下面我们使用wait - notify进行优化
3. 优化版本1 - 使用wait - notify
wait - notify是Object对象中为我们提供的两个native方法, 这两个方法只能在synchronized关键字修饰的同步代码块中使用。Thread.sleep()方法不会释放锁,wait()方法会释放锁,直到被其他线程notify之后,才会重新获得锁。我们对上述异步队列进行改造:
public class AsyncExecutor {private static final Deque<AsyncTaskEntity> taskQueue = new LinkedBlockingDeque<>();public AsyncExecutor() {Thread thread = new Thread(() -> {while (true) {synchronized(this){try {if (taskQueue.isEmpty()) {this.wait();}AsyncTaskEntity entity = taskQueue.pollFirst();execute(entity);} catch (Exception e) {LOGGER.error("异步执行任务出现异常!", e);}}}});thread.setName("异步任务执行器");thread.start();System.out.println("analysis异步队列任务启动完成!");}public synchronized <T> void asyncExecute(AsyncTaskEntity<T> entity) {taskQueue.push(entity);this.notify();}
}
经过上面改造之后,当后台队列中任务为空时,轮训扫描线程就会进入到this.wait()
逻辑,此时会释放synchronized获取到的this锁。因此调用asyncExecute()
方法会正常的获取到this锁。当push数据之后,执行了notify,便会唤醒一个当前this上正在wait()的线程。这种方式就避免了占用资源始终空转的问题。
其实结合线程的三种核心状态可以更好的理解,当调用wait()方法时,该线程会放弃CPU执行权,进入到阻塞状态,直到被其他线程唤醒(notify()
)。
相关文章:

Java高并发系列: 使用wait - notify实现高效异步方法
1. 背景 在项目开发中, 通常会有异步执行操作, 例如: 提交一个异步清空一系列数据库中ID ${_id} 的记录, 这个时候通常的做法是主线程将任务添加到一个异步队列中, 后台维护一个线程不断地循环扫描这个队列, 如果有需要执行的任务, 则执行相应的逻辑. 如下图所示: 2. 一个简…...

业务安全详解
文章目录 一、 业务安全概述1.1 业务安全现状1.1.1 业务逻辑漏洞1.1.2 黑客攻击的目标 二、 业务安全测试2.1 业务安全测试流程2.1.1 测试准备2.1.2 业务调研2.1.3 业务建模2.1.4 业务流程梳理2.1.5 业务风险点识别2.1.6 开展测试2.1.7 撰写报告 三、 业务安全经典场景3.1 业务…...

算法笔记--最大连续1的个数Ⅲ
leetcode题目链接:1004. 最大连续1的个数 III 题目描述 给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。 思路 这里可以转换思路,让题意更加明确:即,求一个最大连续区间…...

Linux CentOS7 添加中文输入法
在安装CentOS7时,现在默认安装了桌面中文系统。可以切换为英文,中英文可以按要求随时更换。而在CentOS7桌面环境下,显示中文非常方便、正确,但不能录入中文。 在远程登录系统的情况下,不论是系统语言(LANG…...

Python接口自动化封装导出excel方法和读写excel数据
一、首先需要思考,我们在页面导出excel,用python导出如何写入文件的 封装前需要确认python导出excel接口返回的是一个什么样的数据类型 如下:我们先看下不对返回结果做处理,直接接收数据类型是一个对象,无法获取返回值…...

React三属性之:refs
作用 refs是为了获取节点,使用场景主要在需要操作dom的时候,比如echarts,就需要真实的dom节点 使用 import React from "react"; class RefsTest extends React.Component{state {value:输入框的值}refPlan React.createRef()logRef ()>{console.log(this.r…...
将Vue项目迁移到微信小程序中
文章目录 一、创建一个Vue.js的应用程序二、构建微信小程序1. 安装微信小程序构建工具2. 在vuejs项目的根目录中创建一个wepy.confgjs文件3. 在vuejs项目的根目录中运行构建 三、错误记录1. 找不到编译器:wepy-compiler-sass 一、创建一个Vue.js的应用程序 使用 Vu…...
php权限调整强制用户退出的解决方案
要强制用户重新登录,你可以采取以下步骤: 当用户登录时,将用户的登录状态和其他相关信息存储在服务器端。例如,你可以将用户ID、用户名或其他标识符存储在服务器的会话(session)中。当管理员修改用户的某些…...

[uniapp]踩坑日记 unexpected character > 1或‘=’>1 报错
在红色报错文档里下滑,找到Show more 根据提示看是缺少标签,如果不是缺少标签,看看view标签内容是否含有<、>、>、<号,把以上符合都进行以<号为例做{{“<”}}处理...
面试求职-经典面试问题
16个经典面试问题回答思路 面试过程中,面试官会向应聘者发问,而应聘者的回答将成为面试官考虑是否接受他的重要依据。对应聘者而言,了解这些问题背后的“猫腻”至关重要。本文对面试中经常出现的一些典型问题进行了整理,并给出相…...
在Linux服务器上部署Tornado项目
要在Linux服务器上部署Tornado项目,你可以按照以下步骤进行操作: 1、准备服务器: 确保你的服务器上安装了Python。Tornado通常与Python 3兼容,因此建议安装Python 3.x。 安装和配置一个Web服务器,如Nginx或Apache&a…...

JWT认证、drf-jwt安装和简单使用、实战之使用Django auth的User表自动签发、实战之自定义User表,手动签发
一 JWT认证 在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证。 我们不再使用Session认证机制,而使用Json Web Token(本质就是token)认证机制。Json web token (JWT), 是为了在网络应用环境…...

conda常用命令及问题解决-创建虚拟环境
好久没写博文了,感觉在学习的过程中还是要注意积累与分享,这样利人利己。 conda包清理,许多无用的包是很占用空间的 conda clean -p //删除没有用的包 conda clean -y -all //删除pkgs目录下所有的无用安装包及cacheconda创建虚拟环境…...

严选算法模型质量保障
在算法模型整个生命周期**(算法模型生命周期:初始训练数据 --> 模型训练 --> 模型评估 --> 模型预估 --> 训练数据)**中,任何环节的问题引入都可能导致算法模型质量问题。所以我们在做模型质量保障的过程中࿰…...

学习Bootstrap 5的第七天
目录 徽章 徽章 实例 上下文徽章 实例 胶囊徽章 实例 元素内的徽章 实例 进度条 基础进度条 实例 进度条高度 实例 彩色进度条 实例 条纹进度条 实例 动画进度条 实例 混合色彩进度条 实例 徽章 徽章 在 Bootstrap 中,徽章(Badg…...

VirtualBox(内有Centos 7 示例安装)
1常见概念以及软件安装 1.1 虚拟化技术: 虚拟化技术指的是将计算机的各种硬件资源加以抽象、转换、分割,最后组合 起来的技术。其目的和作用主要是打破硬件资源不可分的情况,方便程序员自 己集成所需资源。 1.2 Virtual Box 其是虚拟化技术作…...
在 Git 中删除不再位于远程仓库中的本地分支
git 删除远端已经被删除然而本地还存在的分支 1. 修剪不在远程仓库上的跟踪分支 git remote prune origin如果git仓库将branch1被删除,可以用用git remote prune origin删除在本地电脑上的remotes/origin/branch1 git remote show origin可以看到下面所示…...

容器编排学习(九)服务管理与用户权限管理
一 service管理 1 概述 容器化带来的问题 自动调度:在 Pod 创建之前,用户无法预知 Pod 所在的节点,以及 Pod的IP 地址一个已经存在的 Pod 在运行过程中,如果出现故障,Pod也会在新的节点使用新的IP 进行部署应用程…...

【C刷题】day1
一、选择题 1.正确的输出结果是 int x5,y7; void swap() { int z; zx; xy; yz; } int main() { int x3,y8; swap(); printf("%d,%d\n",x, y); return 0; } 【答案】: 3,8 【解析】: 考点: ÿ…...

zabbix配置钉钉告警、和故障自愈、监控java
文章目录 1.配置钉钉告警server 配置web界面创建媒介给用户添加媒介测试告警 实现故障自愈功能监控Javazabbix server 安装java gateway配置 Zabbix Server 支持 Java gateway使用系统内置模板监控 tomcat 主机 1.配置钉钉告警 server 配置 钉钉告警python脚本 脚本1 cd /…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...

GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...

搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...