实现异步的8种方式,你知道几个?
-
一、前言
在编程中,有时候我们需要处理一些费时的操作,比如网络请求、文件读写、数据库操作等等,这些操作会阻塞线程,等待结果返回。为了避免阻塞线程、提高程序的并发处理能力,我们常常采用异步编程。
异步编程是一种编程方式,它通过将任务提交给其他线程或者线程池来实现并发处理,从而提高程序的性能和响应速度。
本文将介绍异步的八种实现方式,并详细阐述异步编程的概念、实现方式和优缺点等问题。
二、异步的八种实现方式
异步编程的实现方式有很多种,下面是常见的八种实现方式:
- 线程异步
- Future异步
- CompletableFuture实现异步
- Spring的@Async异步
- Spring ApplicationEvent事件实现异步
- 消息队列
- ThreadUtil异步工具类
- Guava异步
不同的实现方式适用于不同的场景,我们需要根据具体的需求来选择合适的实现方式。
三、什么是异步?
在讲解异步编程之前,我们先来了解一下异步的概念。
异步是指不需要等待当前操作完成,就能够进行其他操作。例如,我们发出一个网络请求后,可以继续执行其他任务,不必等待网络请求返回结果再执行其他任务,这就是异步操作。
异步的本质是将任务提交给其他线程或者线程池来处理,等待结果时,当前线程不会被阻塞,可以继续处理其他任务。
四、异步编程
异步编程是通过将耗时的任务分配给其他线程或者线程池来实现的,可以提高程序的并发处理能力,让程序具有更好的性能和响应速度。
下面我们将介绍异步编程的八种实现方式。
4.1 线程异步
线程异步是一种最为基础的异步实现方式,它通过创建一个新的线程来执行耗时操作,从而避免阻塞主线程。
线程异步的示例代码如下:
public void doAsyncTask() {Thread thread = new Thread(() -> {// 耗时操作doHeavyTask();});thread.start(); }private void doHeavyTask() {// 耗时操作// ... }
4.2 Future异步
Future异步是通过使用Java的Future接口来实现的,它提供了异步编程的基础能力。
Future异步的示例代码如下:
public void doAsyncTask() {ExecutorService executorService = Executors.newCachedThreadPool();Future<Result> future = executorService.submit(() -> {// 耗时操作return doHeavyTask();});// 在这里处理异步操作的结果try {Result result = future.get();handleResult(result);} catch (Exception e) {handleError(e);} }private Result doHeavyTask() {// 耗时操作// ...return new Result(); }private void handleResult(Result result) {// 处理异步操作的结果// ... }private void handleError(Exception e) {// 处理异步操作的异常// ... }
4.3 CompletableFuture实现异步
CompletableFuture是Java 8中引入的一个异步编程工具类,它提供了更加方便的异步编程方式。
CompletableFuture实现异步的示例代码如下:
public void doAsyncTask() {CompletableFuture<Result> future = CompletableFuture.supplyAsync(() -> {// 耗时操作return doHeavyTask();});// 处理异步操作的结果future.thenAccept(this::handleResult).exceptionally(this::handleError); }private Result doHeavyTask() {// 耗时操作// ...return new Result(); }private void handleResult(Result result) {// 处理异步操作的结果// ... }private void handleError(Throwable throwable) {// 处理异步操作的异常// ... }
4.4 Spring的@Async异步
Spring框架提供了@Async注解来实现异步编程,它可以将一个方法标记为异步执行,并使用ThreadPoolTaskExecutor来执行耗时操作。
Spring的@Async异步的示例代码如下:
@Service public class MyService {@Asyncpublic void doAsyncTask() {// 耗时操作doHeavyTask();}private void doHeavyTask() {// 耗时操作// ...} }
4.5 Spring ApplicationEvent事件实现异步
Spring还提供了ApplicationEvent异步事件,可以在事件监听器中处理耗时操作,从而实现异步编程。
Spring ApplicationEvent事件实现异步的示例代码如下:
@Component public class MyEventListener {@EventListener@Asyncpublic void handleEvent(MyEvent event) {// 耗时操作doHeavyTask();}private void doHeavyTask() {// 耗时操作// ...} }
4.6 消息队列
消息队列是一种基于异步消息传递的异步编程方式,它将消息放入队列中,异步处理这些消息。
常见的消息队列有ActiveMQ、RabbitMQ、RocketMQ等等。
消息队列的示例代码如下:
public void doAsyncTask() {// 发送异步消息sendAsyncMessage();// 处理其他任务// ... }private void sendAsyncMessage() {// 将消息发送到消息队列中// ... }
4.7 ThreadUtil异步工具类
ThreadUtil是一个Java工具类,提供了很多方便的异步编程方法,例如:线程池、定时器、异步调度等等。
ThreadUtil异步工具类的示例代码如下:
public void doAsyncTask() {// 使用线程池执行异步任务ThreadUtil.execAsync(() -> {// 耗时操作doHeavyTask();});// 处理其他任务// ... }private void doHeavyTask() {// 耗时操作// ... }
4.8 Guava异步
Guava是一个Google开发的Java工具类库,提供了很多常用的工具类和方法,其中包括异步编程的实现方式。
Guava异步的示例代码如下:
public void doAsyncTask() {ListenableFuture<Result> future = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool()).submit(() -> {// 耗时操作return doHeavyTask();});Futures.addCallback(future, new FutureCallback<Result>() {@Overridepublic void onSuccess(@Nullable Result result) {handleResult(result);}@Overridepublic void onFailure(Throwable throwable) {handleError(throwable);}}); }private Result doHeavyTask() {// 耗时操作// ...return new Result(); }private void handleResult(Result result) {// 处理异步操作的结果// ... }private void handleError(Throwable throwable) {// 处理异步操作的异常// ... }
以上就是异步编程的八种实现方式,它们各有优缺点,我们需要根据具体的需求来选择合适的实现方式。
相关文章:
实现异步的8种方式,你知道几个?
一、前言 在编程中,有时候我们需要处理一些费时的操作,比如网络请求、文件读写、数据库操作等等,这些操作会阻塞线程,等待结果返回。为了避免阻塞线程、提高程序的并发处理能力,我们常常采用异步编程。 异步编程是一种…...
二叉树的三种遍历
二叉树的遍历可以有:先序遍历、中序遍历、后序遍历先序遍历:根、左子树,右子树中序遍历:左子树、根、右子树后序遍历:左子树、右子树、根下面是我画图理解三种遍历:二叉树里都是分为左子树和右子树。分治思…...

我,30岁程序员被裁了,千万别干全栈
大家好,这里是程序员晚枫,今天是读者投稿。下面开始我们的正文。👇 关注博主👉程序员晚枫 很久了,今天给大家分享一下我从事程序员后,30岁被裁的经历,希望帮到有需要的人。 1、我被裁了 大家好…...

【linux】:进程地址空间
文章目录 前言一、进程地址空间总结前言 本篇文章接着上一篇文章继续讲解进程,主要讲述了进程在运行过程中是如何在内存中被读取的以及为什么要有虚拟地址的存在,CPU在运行过程中是拿到程序的虚拟地址还是真实的物理内存。 一、进程地址空间 下面我们先…...

【保姆级】JMeter Mqtt 压测配置
忽然有个紧急任务要对某个服务做MQTT做压测,紧急实操下JMeter,这里记录下非专业测试员的测试过程、(▽`),欢迎👏大家检查指点( ̄∇ ̄)/下载⏬工具JMeter官方下载地址https://jmeter.apache.org/do…...

C语言数据结构初阶(4)----带头双向循环链表
我们先来看看带头双向循环链表的结构:看到这里我们可能会产生一个想法:这个链表看起来好复杂的样子,是不是它的增删改查比单链表更难写呢?嘿嘿,还真的不是这样的,双向链表的增删改查是很好写的哦࿰…...

原生javascript手写一个丝滑的轮播图
通过本文,你将学到: htmlcssjs 没错,就是html,css,js,现在是框架盛行的时代,所以很少会有人在意原生三件套,通过本文实现一个丝滑的轮播图,带你重温html,css和js基础知识。 为什么选用轮播图做示例&…...

【Linux】进程优先级(进程优先级 Linux下优先级 用top命令更改已存在进程的nice 其他概念 进程切换)
文章目录进程优先级Linux下优先级用top命令更改已存在进程的nice:其他概念进程切换进程优先级 我们作为使用者一般不关心优先级,它跟我们的调度器有很大的关系,调度器是为了跟均衡的调度进程。 什么叫做优先级? 优先级和权限是两…...

2016年chatGPT之父Altman与马斯克的深度对话(值得一看)
2016年9月,现今OpenAI CEO,ChatGPT之父,时任创投公司Y Combinator的总裁Sam Altman在特斯拉加州弗里蒙特工厂采访了埃隆马斯克。马斯克阐述了创建OpenAI的初衷,以及就他而言,对于未来最为重要的五件事。这是OpenAI的两…...

基于vscode开发vue3项目的详细步骤教程 3 前端路由vue-router
1、Vue下载安装步骤的详细教程(亲测有效) 1_水w的博客-CSDN博客 2、Vue下载安装步骤的详细教程(亲测有效) 2 安装与创建默认项目_水w的博客-CSDN博客 3、基于vscode开发vue项目的详细步骤教程_水w的博客-CSDN博客 4、基于vscode开发vue项目的详细步骤教程 2 第三方图标库FontAw…...

【C语言】每日刷题 —— 牛客语法篇(5)
前言 大家好,继续更新专栏 c_牛客,不出意外的话每天更新十道题,难度也是从易到难,自己复习的同时也希望能帮助到大家,题目答案会根据我所学到的知识提供最优解。 🏡个人主页:悲伤的猪大肠9的博…...

操作系统(2.1)--进程的描述与控制
目录 一、前驱图和程序执行 1.前驱图 2.程序顺序执行 2.1 程序的顺序执行 2.2 程序顺序执行时的特征 3. 程序并发执行 3.1程序的并发执行 3.2 程序并发执行时的特征 一、前驱图和程序执行 1.前驱图 前趋图:是一个有向无循环图,用于描述进程之间执行的前后…...
JAVA查看动态代理类
JAVA查看代理类 1. 代理类 class 生成 System.setProperty // jdk8及之前的设置System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");// or System.getProperties().put("sun.misc.ProxyGenerator.saveGenerated…...

Chapter2 : SpringBoot配置
尚硅谷SpringBoot顶尖教程 1. 全局配置文件 SpringBoot使用一个全局的配置文件 application.properties 或者 application.yml ,该配置文件放在src/main/resources目录或者类路径/config目录下面, 可以用来修改SpringBoot自动配置的默认值。 yml是YA…...

手撕单链表练习
Topic 1:LeetCode——203. 移除链表元素203. 移除链表元素 - 力扣(LeetCode)移除链表中的数字6操作很简单,我们只需要把2的指向地址修改就好了,原来的指向地址是6现在改为3这个思路是完全正确的,但是在链表…...

Kubuntu安装教程
文章目录Kubuntu介绍下载Kubuntu在VMware虚拟机中安装Kubuntu1. 点击“创建新的虚拟机”2. 选择“自定义(高级)”3. 按照下图所示进行设置设置网络4. 点击“自定义硬件”5. 开启虚拟机6. 进入安装界面,选择中文,之后点击“安装Kub…...

[蓝桥杯] 树状数组与线段树问题(C/C++)
文章目录 一、动态求连续区间和 1、1 题目描述 1、2 题解关键思路与解答 二、数星星 2、1 题目描述 2、2 题解关键思路与解答 三、数列区间最大值 3、1 题目描述 3、2 题解关键思路与解答 标题:树状数组与线段树问题 作者:Ggggggtm 寄语:与其…...
Matlab-Loma Prieta 地震分析
此示例说明如何将带时间戳的地震数据存储在时间表中以及如何使用时间表函数来分析和可视化数据。 加载地震数据 示例文件quake.mat包含 1989 年 10 月 17 日圣克鲁斯山脉 Loma Prieta 地震的 200 Hz 数据。这些数据由加州大学圣克鲁斯分校查尔斯F里希特地震实验室的 Joel Yelli…...
Spring Boot全局异常处理
使用注解方式处理全局异常使用 ControllerAdvice (RestControllerAdvice) 配合 ExceptionHandler适用于返回数据的请求(一般是RESTful接口规范下的JSON报文)package com.example.exception;import org.slf4j.Logger; import org.s…...

websocket每隔5秒给服务端send一次信息
websocket轮询每隔5秒给服务端send一次信息,主要功能点如下:socket 采用了定时器 setInterval() 需要清除定时器否则会报错监听了突然关闭浏览器窗口,destroyed里面直接监听 window.removeEventListener("beforeu…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...

Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
flow_controllers
关键点: 流控制器类型: 同步(Sync):发布操作会阻塞,直到数据被确认发送。异步(Async):发布操作非阻塞,数据发送由后台线程处理。纯同步(PureSync…...

echarts使用graphic强行给图增加一个边框(边框根据自己的图形大小设置)- 适用于无法使用dom的样式
pdf-lib https://blog.csdn.net/Shi_haoliu/article/details/148157624?spm1001.2014.3001.5501 为了完成在pdf中导出echarts图,如果边框加在dom上面,pdf-lib导出svg的时候并不会导出边框,所以只能在echarts图上面加边框 grid的边框是在图里…...
LUA+Reids实现库存秒杀预扣减 记录流水 以及自己的思考
目录 lua脚本 记录流水 记录流水的作用 流水什么时候删除 我们在做库存扣减的时候,显示基于Lua脚本和Redis实现的预扣减 这样可以在秒杀扣减的时候保证操作的原子性和高效性 lua脚本 // ... 已有代码 ...Overridepublic InventoryResponse decrease(Inventor…...