
- 外文名
- Asynchronous
- 中文名
- 异步
-
同步和异步的区别
2018-10-25 19:10:42原文地址:同步和异步,区别 同步: 同步的思想是:所有的操作都做完,才返回给用户。这样用户在线等待的时间太长,给用户一种卡死了的感觉(就是系统迁移中,点击了迁移,界面就不动了,但是程序还在执行,卡死了的...同步和异步的区别
博主的学习记录
原文地址
同步和异步,区别(已经不存在了)。
同步
所有的操作都做完,才返回给用户。这样用户在线等待的时间太长,给用户一种卡死了的感觉(就是系统迁移中,点击了迁移,界面就不动了,但是程序还在执行,卡死了的感觉)。这种情况下,用户不能关闭界面,如果关闭了,即迁移程序就中断了。
异步
将用户请求放入消息队列,并反馈给用户,系统迁移程序已经启动,你可以关闭浏览器了。然后程序再慢慢地去写入数据库去。这就是异步。但是用户没有卡死的感觉,会告诉你,你的请求系统已经响应了。你可以关闭界面了。同步,是所有的操作都做完,才返回给用户结果。即写完数据库之后,再响应用户,用户体验不好。
异步,不用等所有操作都做完,就相应用户请求。即先响应用户请求,然后慢慢去写数据库,用户体验较好。异步操作例子
为了避免短时间大量的数据库操作,就使用缓存机制,也就是消息队列。先将数据放入消息队列,然后再慢慢写入数据库。
引入消息队列机制,虽然可以保证用户请求的快速响应,但是并没有使得我数据迁移的时间变短(即80万条数据写入mysql需要1个小时,用了redis之后,还是需要1个小时,只是保证用户的请求的快速响应。用户输入完http url请求之后,就可以把浏览器关闭了,干别的去了。如果不用redis,浏览器不能关闭)。
同步就没有任何价值了吗?
银行的转账功能。
-
SpringBoot异步处理任务
2020-06-28 10:06:192)异步:直接返回给用户指定的状态,同时程序在后台继续运行,用户不用等待。 实现 同步实现 @Autowired private TaskAsync taskAsync; /** * 同步处理的方式 */ @GetMapping("/test2") public ...名词解释
1)同步:等用户所有操作结束后,才会返回程序的处理状态。
2)异步:直接返回给用户指定的状态,同时程序在后台继续运行,用户不用等待。
实现
同步实现
@Autowired private TaskAsync taskAsync; /** * 同步处理的方式 */ @GetMapping("/test2") public String test2() { taskAsync.getTest2(); System.out.println(Thread.currentThread().getName() + "==========主线程名"); return "同步,正在解析......"; }
@Component public class TaskAsync { public void getTest2() { Building building = new Building(); synchronized (building) { try { for (int i = 0; i <= 100; i++) { System.out.println(Thread.currentThread().getName() + "----------同步:>" + i); building.wait(200); } } catch (InterruptedException e) { e.printStackTrace(); } } } }
这种同步的方式处理,会发现,当这100此循环完成后,页面才会返回 :同步,正在解析......。当后台在循环处理时,前台的页面始终处于等待状态。可以发现,使用都是一个线程在处理:
异步实现方式一
使用线程池,创建新的线程去处理,如下:
/** * 异步处理方式一:线程池,创建新线程处理 */ @GetMapping("/test3") public String test3() { ExecutorService service = Executors.newFixedThreadPool(5); RunnableTask1 task1 = new RunnableTask1(); service.execute(task1); System.out.println("=========》当前线程名:" + Thread.currentThread().getName()); return "异步,正在解析......"; }」
public class RunnableTask1 implements Runnable { @Override public void run() { Building building = new Building(); synchronized (building) { try { for (int i = 0; i <= 100; i++) { System.out.println(Thread.currentThread().getName() + "----------异步:>" + i); building.wait(200); } } catch (Exception e) { e.printStackTrace(); } } } }
我们看控制台,会发现,主线程和处理任务的线程,不是一个线程,也就是,当页面请求后,主线程会返回我们想要返回的标识,这里返回的是一个字符串:异步,正在解析......,而线程池新开了一个线程,在后台处理业务逻辑。所以,此时访问接口后,会立马返回,页面不用等待,处理逻辑在后台默默进行。控制台如下:
异步实现方式二
这种方式,是SpringBoot自身的一种异步方式,使用注解实现,非常方便。
SpringBoot要使用@Async需要以下两个步骤:
1.使用@EnableAsync开启异步;(在项目的启动类上)
2.定义Spring组件,使用@Component和@Async;
注意,这里的异步方法,只能在自身之外调用,在本类调用是无效的。
/** * 异步方法 * 有@Async注解的方法,默认就是异步执行的,会在默认的线程池中执行,但是此方法不能在本类调用;启动类需添加直接开启异步执行@EnableAsync。 */ @GetMapping("/test1") public String test1() { taskAsync.getTest1(); System.out.println(Thread.currentThread().getName() + "========================="); return "异步,正在解析......"; }
import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; @Component public class TaskAsync { @Async public String getTest1() { Building building = new Building(); synchronized (building) { try { for (int i = 1; i <= 100; i++) { System.out.println(Thread.currentThread().getName() + "----------异步:>" + i); building.wait(200); } return "执行异步任务完毕"; } catch (Exception ex) { ex.printStackTrace(); } } return Thread.currentThread().getName() + "执行完毕"; } }
看控制台,会发现,页面发出请求后,主线程会返回,而内置的线程池会新开线程,在后台执行任务。此时页面不用等待,可以继续其他操作。
可以看到,很多情况下,异步处理,是一种很常见,而且很高效的方式,个人比较喜欢使用springBoot自带的注解方式,只用两个注解即可了。
-
Java之手写异步任务
2020-04-03 09:47:28为什么需要异步任务?有些代码可能影响程序性能,并且不需要实时同步执行,这部分代码就可以放到异步任务中,以减少响应时间。比如在用户操作软件的时候需要记录一些操作日志,频繁写入db的操作会影响用户体验。 ...为什么需要异步任务?有些代码可能影响程序性能,并且不需要实时同步执行,这部分代码就可以放到异步任务中,以减少响应时间。比如在用户操作软件的时候需要记录一些操作日志,频繁写入db的操作会影响用户体验。
实现思路: 首先创建一个AbstractQueue类,用于存放任务队列。然后创建一个AbstractAsynTask类,用于管理AbstractQueue队列。
下面是具体实现:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; /** * @Author: jack * @Description:抽象异步队列 */ public abstract class AbstractQueue { private static Logger log = LoggerFactory.getLogger(AbstractQueue.class); //队列空闲时间 3分钟 private static final int timeout = 3 * 60 * 1000 ; //当前任务大小 private volatile AtomicInteger size = new AtomicInteger(); //线程启动开关 private boolean isRun = false; private volatile Queue<Object> queue = new ConcurrentLinkedQueue(); //线程,用于遍历队列 private volatile Thread thread = null; //最后执行时间 private volatile long lastTime = System.currentTimeMillis(); //队列名称 public String queueName = "抽象队列"; //线程结果汇总 private volatile StringBuilder resultBuilder = new StringBuilder(); //总数 private volatile AtomicInteger total = new AtomicInteger(); //成功数 private volatile AtomicInteger success = new AtomicInteger(); //失败数 private volatile AtomicInteger fail = new AtomicInteger(); public void add(Object dto) { queue.add(dto); size.incrementAndGet(); total.incrementAndGet(); } private void stop() { log.error("【" + queueName + "】,线程关闭"); isRun = false; resultBuilder.append("总数:" + total.intValue() + ",成功数:" + success.intValue() + ",失败数:" + fail.intValue()); log.error(resultBuilder.toString()); } private void start() { log.error("【" + queueName + "】,线程开启"); isRun = true; thread.start(); } public int getSize() { return size.get(); } public AbstractQueue(String queueName) { this.queueName = queueName; resultBuilder.append("【" + queueName + "】,执行汇总:").append("\r\n"); thread = new Thread(() -> { while (isRun) { Object emailDto = null; try { if (!queue.isEmpty()) { lastTime = System.currentTimeMillis(); emailDto = queue.poll(); size.decrementAndGet(); task(emailDto); success.incrementAndGet(); } long currentTime = System.currentTimeMillis(); if ((currentTime - lastTime) >= timeout) { stop(); } else { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); fail.incrementAndGet(); } } }); start(); } abstract public void task(Object dto); public boolean isAlive() { return thread.isAlive() && isRun; } }
import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * @Author: jack * @Description:抽象异步任务 */ public abstract class AbstractAsynTask { //每个队列最大容量 public static final int max_capacity = 500; //队列列表 public volatile List<AbstractQueue> queueList =new ArrayList<>(); public void add(Object dto){ boolean isAdd = false; Iterator ite = queueList.iterator(); while(ite.hasNext()){ AbstractQueue queue = (AbstractQueue) ite.next(); if(queue.getSize() >= max_capacity){ continue; } if(!queue.isAlive()){ ite.remove(); queueList.add(createNewQueue()); } queue.add(dto); isAdd = true; break; } if(!isAdd){ AbstractQueue queue = doCreateNewQueue(); queue.add(dto); queueList.add(queue); } } public AbstractQueue doCreateNewQueue(){ return createNewQueue(); } abstract public AbstractQueue createNewQueue(); public int getQueueSize(){ return queueList.size(); } }
到这已经大功告成了,接下来写个具体实现,测试一下异步任务。
public class SendMsgQueue extends AbstractQueue { @Override public void task(Object dto) { try { System.out.println("【"+queueName+"】"+"sending content :"+dto); Thread.sleep(50); System.out.println("【"+queueName+"】"+"send finish..."); } catch (InterruptedException e) { e.printStackTrace(); } } public SendMsgQueue(String queueName){ super(queueName); } }
public class SendMsgAsynTask extends AbstractAsynTask { @Override public AbstractQueue createNewQueue() { return new SendMsgQueue("消息队列"+getQueueSize()); } }
然后是测试类
public class test { public static void main(String[] args) { SendMsgAsynTask task = new SendMsgAsynTask(); for(int i=0;i<10000;i++){ task.add("hello world"); } } }
执行后控制台部分输出如下
[ERROR]-[Thread: main]-[com.recovery.www.task.asyn.AbstractQueue.start()]: 【消息队列17】,线程开启 【消息队列16】sending content :hello world 【消息队列17】sending content :hello world 2020-04-03 09:39:56 [ERROR]-[Thread: main]-[com.recovery.www.task.asyn.AbstractQueue.start()]: 【消息队列18】,线程开启 【消息队列18】sending content :hello world 2020-04-03 09:39:56 [ERROR]-[Thread: main]-[com.recovery.www.task.asyn.AbstractQueue.start()]: 【消息队列19】,线程开启 【消息队列19】sending content :hello world 【消息队列0】send finish... 【消息队列1】send finish... 【消息队列2】send finish...
可以看到执行10000个任务总共开启了19个线程。这些任务在线程中串行执行
-
使用ES6新特性async await进行异步处理
2018-07-12 15:56:30我们往往在项目中会遇到这样的业务需求,就是首先...那是相当恶心的,下面我就来讲一下如何使用ES6的新特性async await进行异步处理,使上述情况就好像写同步代码一样,首先我们先举个例子: 先写上json文件: cod...我们往往在项目中会遇到这样的业务需求,就是首先先进行一个ajax请求,然后再进行下一个ajax请求,而下一个请求需要使用上一个请求得到的数据,请求少了还好说,如果多了,就要一层一层的嵌套,就好像有点callback的写法了,那是相当恶心的,下面我就来讲一下如何使用ES6的新特性async await进行异步处理,使上述情况就好像写同步代码一样,首先我们先举个例子:
先写上json文件:
code.json:{ "code":0, "msg":"成功" }
person.json:
{ "code":0, "list":[ { "id":1, "name":"唐僧" }, { "id":2, "name":"孙悟空" }, { "id":3, "name":"猪八戒" }, { "id":4, "name":"沙僧" } ] }
比如我们有两个请求,如下,这里用的axios:
function getCode(){ return axios.get('json/code.json'); } function getlist(params){ return axios.get('json/person.json',{params}) }
我们第二个请求获取列表的时候需要使用第一个请求得到的code值,只有code值为0时,才能请求,而且当做参数传进去,那么我们看一下常规的做法吧
function getFinal(){ console.log("我是getFinal函数") getCode().then(function(res){ if(res.data.code == 0){ console.log(res.data.code); var params = { code:res.data.code } getlist(params).then(function(res){ if(res.data.code == 0){ console.log(res.data.list); } }) } }) } getFinal();
看结果
虽然结果出来了,可是这种写法真的挺难受的,下面来一个async await的写法async function getResult(){ console.log("我是getResult函数") let code = await getCode(); console.log(code.data.code); if(code.data.code == 0){ var params = { code:code.data.code } let list = await getlist(params); console.log(list.data.list); } } getResult();
下面看结果
当然还剩最后一点,处理异常,可以加上try catchasync function getResult(){ console.log("我是getResult函数") try{ let code = await getCode(); console.log(code.data.code); if(code.data.code == 0){ var params = { code:code.data.code } let list = await getlist(params); console.log(list.data.list); } }catch(err){ console.log(err); } } getResult();
个人认为做vue项目的时候,如果对于异常没有特殊处理,可以不加try catch,因为打印出来的错误跟vue自己报的错误是一样的,而且还是黑的字体,不如醒目的红色来的痛快啊!当然如果要对错误进行特殊处理,那么就加上吧
代码风格是不是简便了许多,而且异步代码变成了同步代码,下面我稍微讲一下后者写法的代码执行顺序
首先在 function 前面加 async 用来说明这个函数是一个异步函数,当然,async是要和await配合使用的,第一个请求
let code = await getCode();
await 意思是等一下,等着getCode()这个函数执行完毕,得到值后再赋值给code,然后再用code的值进行下一步操作,就是这么简单!!!赶紧去改代码!!
-
异步串口通信
2012-07-12 22:09:19多线程异步串口通信, 通过底层API实现,VS2010环境编码 在本人博客中有详尽的文档说明,介绍串口通信的知识 http://blog.csdn.net/mingojiang/article/details/7713529 -
异步编排
2020-08-26 16:28:39异步编排 -
通俗讲解 同步、异步、阻塞、非阻塞 编程
2020-06-17 15:09:01# 真正意义上的 异步IO 是说内核直接将数据拷贝至用户态的内存单元,再通知程序直接去读取数据。 # select / poll / epoll 都是同步IO的多路复用模式 1.同步和异步 # 同步和异步关注的是消息通信机制 # 所谓... -
异步 等待异步 异步回调 获取异步结果
2017-01-04 10:43:16异步 是通过委托来实现的 异步就是另开一个线程 去执行委托里面的方法体 整个代码全部一下子贴出来 Console.WriteLine("程序开始"); Func fun = t => { //等待2秒 容易看效果 Thread.Sleep(2000); Con -
异步短信通知
2019-10-31 17:15:25检查发现是批量短信接口超时,前端直接抛异常了,改为异步发送…… @Autowired private ThreadPoolTaskExecutor executor; // mobileMessageReadService.batchSend(messages); // store.setS... -
【nodejs】封装异步API,理解回调函数
2020-04-03 23:19:30同步、异步、多线程与多进程同步/异步是单线程并发、并行和多线程、多进程2. 回调函数本质解决办法 问题:封装含异步的步骤时,发现希望值和实际值不一致 1. 同步、异步、多线程与多进程 同步/异步是单线程 同步... -
Dubbo异步调用
2020-04-15 15:12:42异步调用, 对于 Provider 端不需要做特别的配置。 Consumer 配置: <dubbo:reference id="asyncService" interface="com.x.x.AsyncService"> <dubbo:method name="testAsync" async="true"/> <... -
echarts异步数据加载(在下拉框选择事件中异步更新数据)
2017-01-22 01:30:57在接触echarts这期间也没有总结什么东西,今天我就来总结一下如何在echart中异步加载数据,在实际的工作的中对数据的刷选非常常见,比如在下拉框中选择,时间选择等的一些事件中异步加载数据。一个很常见的筛选如图... -
spring boot如何使用异步方法
2020-10-30 23:30:57首先在主启动类上添加@EnableAsync注解 然后在方法上添加@Async注解 然后访问此方法即为异步方法 -
异步方法中取消异步操作
2018-12-24 14:29:301、在异步方法中取消异步操作,第一步必须声明CancellationToken和CancellationTokenSource两个类对象,并将两个类通过 CancellationTokenSource 对象的token属性关联; CancellationTokenSource cts = new ... -
java异步计算
2018-08-11 10:39:481. 什么是异步计算? 异步计算是分布式计算的一种实现方式,开发人员不必花费太多的硬件成本,即可通过软件方式以更低的成本实现大规模运算需要的处理能力。 2. 为什么我们要使用异步计算? 顾名思义就是不通... -
一篇文章彻底搞懂异步,同步,setTimeout,Promise,async
2019-06-10 13:18:14之前翻看别的大佬的...观看了几篇之后还是没有怎么看懂,于是自己开始分析代码,并整理了此文章,我相信通过此文章朋友们能对异步同步还有,setTimeout,Promise,async这些内容了然于胸,接下来让我们走入正题: ... -
JavaScript_同步与异步、Promise、async/await、微任务与宏任务
2021-01-14 20:25:14JavaScript_同步与异步、Promise、async/await 同步与异步示例: console.log("a") console.log("b") setTimeout(() => {console.log("异步操作")}, 2000) console.log("c") console.log("d") JQuery 的 ... -
使用SpringBoot的@Async实现异步调用方法,以及自己开启新线程异步调用
2018-09-12 11:25:14springboot的@Async注解实现异步 要在springboot中使用异步调用方法,只要在被调用的方法上面加上@Async就可以了 1.准备工作 准备一个springboot工程,在Application类上加上EnableAsync注解开启异步 ... -
Spring Boot---(4)SpringBoot异步处理任务
2018-01-12 17:21:06欢迎关注公众号:java4all 场景:现在需要上传一个Excel表格,数据量几万条,而且,上传解析后还需要进行计算,然后插入数据库。...所以,这里需要做异步处理: 1.上传-->返回正在解析的标志; 2.解... -
C# 异步TCP Socket 多人聊天室(1服务器,N客户端)
2011-08-08 02:16:37C# 异步TCP Socket 多人聊天室(1服务器,N客户端) C# 异步TCP Socket 多人聊天室(1服务器,N客户端) C# 异步TCP Socket 多人聊天室(1服务器,N客户端) C# 异步TCP Socket 多人聊天室(1服务器,N客户端) C# ... -
什么是异步
2018-12-22 08:53:27说说你的理解,什么是异步。 由于各个语言处理异步的机制有差异,我们这里只说 JS 中的异步。 怎么样的代码是异步代码? 我们先不深入异步概念,先从「表象」来看看怎么样的代码是异步代码: 异步代码的书写顺序... -
异步通知
2017-08-18 14:28:02一、什么是异步通知 异步通知类似于中断的机制。当设备可写时,设备驱动函数发送一个信号给内核,告知内核有数据可读,在条件不满足之前,并不会造成阻塞。而不像之前学的阻塞型IO和poll,它们是调用函数进去检查,... -
SpringBoot 异步执行方法,接口异步调用方法
2020-07-14 09:09:43SpringBoot 异步执行方法,在接口调用时开启一个新线程做一些操作,这个操作结果,不影响返回值 项目启动类或者任意被Spring容器管理的类,必须要有一个`@EnableAsync`注解,标识项目开启异步功能 然后在需要异步... -
异步提交表单
2020-09-04 17:10:48异步提交表单 异步提交表单的步骤 所谓异步提交表单,就是不再使用表单的提交按钮实现表单的提交功能,而是通过Ajax异步交互方式实现表单提交。具体实现步骤如下: 获取表单及所有表单组件对应的数据值。 将所有表单... -
Ajax同步、异步、异步刷新
2017-07-20 17:30:07之前一直都是顺口都说异步刷新,今天就好好的学习了一下Ajax的异步、同步与异步刷新。 异步与同步他与刷新并不关联。要注意! JQuery中的Ajax方法有个属性async用于控制同步与异步的,默认情况下是true,即... -
Python 异步请求
2020-02-15 13:07:55Python 异步请求原文地址:Python 异步请求 -
java 异步等待_Java中的异步等待
2020-07-02 11:05:52java 异步等待 编写异步代码很困难。 试图了解异步代码应该做什么的难度更大。 承诺是尝试描述延迟执行流程的一种常见方式:首先做一件事,然后再做另一件事,以防万一出错时再做其他事情。 在许多语言中,承诺已... -
ajax 同步和异步区别?
2019-01-09 08:57:06ajax 同步和异步区别? 我们在使用 ajax 一般都会使用异步处理。 异步处理呢就是我们通过事件触发到 ajax,请求服务器,在这个期间无论服务器有没有响应,客户端的其他代码一样可以运行。 同步处理:我们通过实践... -
WebService异步
2015-04-10 11:05:05对于服务端和客户端互相调用的程序,我认为异步可以分为客户端异步、服务端异步,并且他们异步操作互不影响。 从是否等待来看,我觉得可以分为等待异步方式和不等待的异步方式。 异步代码编写上,主要有两种方式:... -
c#同步异步调用和异步回调
2018-05-11 16:27:20但是本方法需要在执行结束后才可以执行一些操作,只是用单纯的异步操作不能达到目的,因此,使用异步回调,当耗时方法执行结束后会自动执行回调函数。注:使用异步的时候,要尤其注意线程安全问题,当...
-
感知拓扑的虚拟机放置,用于云数据中心的网络优化
-
歌声合成从入门到精通
-
vue watch监听不到 对象,
-
基于并行启发式约简的配电网故障诊断方法
-
libFuzzer视频教程
-
力扣剑指offer03
-
新型恒星传感器自主在轨校准方法
-
moloch-2.3.0-1.x86_64.rpm
-
Template Cluster Hadoop.xml
-
响应式编程入门与实战(Reactor、WebFlux、R2DBC)
-
linux基础入门和项目实战部署系列课程
-
Python启蒙到架构师的核心技术精讲课程
-
关于美国保险.pptx
-
5G 如何在推动工业运行中发挥出至关重要的作用?
-
ZZULIOJ 1118: 数列有序
-
叮当快药的“快”,美团买药的“轻”,都不及一个“对”?
-
Jetson Xavier硬件自启动
-
实施情感检测分类器-源码
-
C++11 14 17 20 多线程从原理到线程池实战
-
面试题-7Servlet