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

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&#xff0c;如果可以翻转最多 k 个 0 &#xff0c;则返回 数组中连续 1 的最大个数 。 思路 这里可以转换思路&#xff0c;让题意更加明确:即&#xff0c;求一个最大连续区间…...

Linux CentOS7 添加中文输入法

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

Python接口自动化封装导出excel方法和读写excel数据

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

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. 找不到编译器&#xff1a;wepy-compiler-sass 一、创建一个Vue.js的应用程序 使用 Vu…...

php权限调整强制用户退出的解决方案

要强制用户重新登录&#xff0c;你可以采取以下步骤&#xff1a; 当用户登录时&#xff0c;将用户的登录状态和其他相关信息存储在服务器端。例如&#xff0c;你可以将用户ID、用户名或其他标识符存储在服务器的会话&#xff08;session&#xff09;中。当管理员修改用户的某些…...

[uniapp]踩坑日记 unexpected character > 1或‘=’>1 报错

在红色报错文档里下滑&#xff0c;找到Show more 根据提示看是缺少标签&#xff0c;如果不是缺少标签&#xff0c;看看view标签内容是否含有<、>、>、<号,把以上符合都进行以<号为例做{{“<”}}处理...

面试求职-经典面试问题

16个经典面试问题回答思路 面试过程中&#xff0c;面试官会向应聘者发问&#xff0c;而应聘者的回答将成为面试官考虑是否接受他的重要依据。对应聘者而言&#xff0c;了解这些问题背后的“猫腻”至关重要。本文对面试中经常出现的一些典型问题进行了整理&#xff0c;并给出相…...

在Linux服务器上部署Tornado项目

要在Linux服务器上部署Tornado项目&#xff0c;你可以按照以下步骤进行操作&#xff1a; 1、准备服务器&#xff1a; 确保你的服务器上安装了Python。Tornado通常与Python 3兼容&#xff0c;因此建议安装Python 3.x。 安装和配置一个Web服务器&#xff0c;如Nginx或Apache&a…...

JWT认证、drf-jwt安装和简单使用、实战之使用Django auth的User表自动签发、实战之自定义User表,手动签发

一 JWT认证 在用户注册或登录后&#xff0c;我们想记录用户的登录状态&#xff0c;或者为用户创建身份认证的凭证。 我们不再使用Session认证机制&#xff0c;而使用Json Web Token&#xff08;本质就是token&#xff09;认证机制。Json web token (JWT), 是为了在网络应用环境…...

conda常用命令及问题解决-创建虚拟环境

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

严选算法模型质量保障

在算法模型整个生命周期**&#xff08;算法模型生命周期&#xff1a;初始训练数据 --> 模型训练 --> 模型评估 --> 模型预估 --> 训练数据&#xff09;**中&#xff0c;任何环节的问题引入都可能导致算法模型质量问题。所以我们在做模型质量保障的过程中&#xff0…...

学习Bootstrap 5的第七天

目录 徽章 徽章 实例 上下文徽章 实例 胶囊徽章 实例 元素内的徽章 实例 进度条 基础进度条 实例 进度条高度 实例 彩色进度条 实例 条纹进度条 实例 动画进度条 实例 混合色彩进度条 实例 徽章 徽章 在 Bootstrap 中&#xff0c;徽章&#xff08;Badg…...

VirtualBox(内有Centos 7 示例安装)

1常见概念以及软件安装 1.1 虚拟化技术&#xff1a; 虚拟化技术指的是将计算机的各种硬件资源加以抽象、转换、分割&#xff0c;最后组合 起来的技术。其目的和作用主要是打破硬件资源不可分的情况&#xff0c;方便程序员自 己集成所需资源。 1.2 Virtual Box 其是虚拟化技术作…...

在 Git 中删除不再位于远程仓库中的本地分支

git 删除远端已经被删除然而本地还存在的分支 1. 修剪不在远程仓库上的跟踪分支 git remote prune origin如果git仓库将branch1被删除&#xff0c;可以用用git remote prune origin删除在本地电脑上的remotes/origin/branch1 git remote show origin可以看到下面所示&#xf…...

容器编排学习(九)服务管理与用户权限管理

一 service管理 1 概述 容器化带来的问题 自动调度&#xff1a;在 Pod 创建之前&#xff0c;用户无法预知 Pod 所在的节点&#xff0c;以及 Pod的IP 地址一个已经存在的 Pod 在运行过程中&#xff0c;如果出现故障&#xff0c;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"&#xff0c;x, y); return 0; } 【答案】&#xff1a; 3&#xff0c;8 【解析】&#xff1a; 考点&#xff1a; &#xff…...

zabbix配置钉钉告警、和故障自愈、监控java

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

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

DBLP数据库是什么?

DBLP&#xff08;Digital Bibliography & Library Project&#xff09;Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高&#xff0c;数据库文献更新速度很快&#xff0c;很好地反映了国际计算机科学学术研…...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...

面试高频问题

文章目录 &#x1f680; 消息队列核心技术揭秘&#xff1a;从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"&#xff1f;性能背后的秘密1.1 顺序写入与零拷贝&#xff1a;性能的双引擎1.2 分区并行&#xff1a;数据的"八车道高速公路"1.3 页缓存与批量处理…...

6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙

Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...