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 /…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...
Docker 镜像上传到 AWS ECR:从构建到推送的全流程
一、在 EC2 实例中安装 Docker(适用于 Amazon Linux 2) 步骤 1:连接到 EC2 实例 ssh -i your-key.pem ec2-useryour-ec2-public-ip步骤 2:安装 Docker sudo yum update -y sudo amazon-linux-extras enable docker sudo yum in…...
【Docker 02】Docker 安装
🌈 一、各版本的平台支持情况 ⭐ 1. Server 版本 Server 版本的 Docker 就只有个命令行,没有界面。 Platformx86_64 / amd64arm64 / aarch64arm(32 - bit)s390xCentOs√√Debian√√√Fedora√√Raspbian√RHEL√SLES√Ubuntu√√√√Binaries√√√ …...
SpringCloud——Nacos
1、核心功能: 服务注册与发现: 服务实例可动态注入到Nacos中,消费者通过服务名发现可用实例。 // 启用EnableDiscoveryClient注解启用Nacos SpringBootApplication EnableDiscoveryClient public class UserServiceApplication {public st…...
