.Net技术栈下的异步,你还在用同步方式进行开发吗?
关于异步,其实是个老生常谈的话题,也是各大公司面试常问的问题之一.本文就几个点来介绍异步解决的问题
注:对多线程的运行的基本机制要了解
1、介绍
有人可能会有疑问,为什么并行,非得用异步.多线程也已可以啊,多开两个线程不就行了.
案例分析:现在有一个生活场景.需要煮饭(假设需要20分钟-机器煮)、洗衣服(假设需要25分钟-机器洗)、蒸菜(假设需要10分钟-机器蒸).并且昨晚之后我需要告知哥们.
(1)、同步
如果采用同步的方式(我先煮饭,把米放到电饭煲里,然后站在电饭煲前面等,什么事都不能干,一直等到饭煮好.接下去在洗衣服....以此类推),那么我需要一件一件做,那么我总共要花费20+25+10=55分钟.显然这种方式很蠢.实例代码如下:
class Program
{
static void Main(string[] args)
{
CookRice();
CookDish();
DoLaundry();
Console.WriteLine("哥们,全都搞定了");
Console.ReadKey();
} /// <summary>
/// 煮饭
/// </summary>
static void CookRice()
{
Thread.Sleep(20 * 1000 * 60);
} /// <summary>
/// 蒸菜
/// </summary>
static void CookDish()
{
Thread.Sleep(10 * 1000 * 60);
} /// <summary>
/// 洗衣服
/// </summary>
static void DoLaundry()
{
Thread.Sleep(25 * 1000 * 60);
}
}
(2)、多线程优化
ok,上面的代码执行方式显然是很蠢的,因为那样会占用我(线程)大量的时间.
注意:这里要从执行时间这个角度去考虑,因为作为Web开发,一个用户请求从开始到结束,是有时间限制的,如果你一个请求(报表之类的特殊业务除外,指互联网场景)超过1秒,用户可能都无法忍受。 这里的请求在.net下指代线程.
ok,那只能对这个耗时任务,进行拆解,当然前提是他可以拆解(存在并行化的可能),我们这个例子显然是可以的,于是,我这么做,先把米放到电饭煲里面,不在停留,接着立马把衣服放到洗衣机,最后再把菜放到蒸锅里.然后我去干别的事情了.代码如下:
class Program
{
static void Main(string[] args)
{
var t1=Task.Run(() => CookRice());
var t2 = Task.Run(() => CookDish());
var t3 = Task.Run(() => DoLaundry());
Task.WaitAll(t1, t2, t3);
Console.WriteLine("哥们,全部搞定了");
Console.ReadKey();
} /// <summary>
/// 煮饭
/// </summary>
static void CookRice()
{
Thread.Sleep(20 * 1000 * 60);
} /// <summary>
/// 蒸菜
/// </summary>
static void CookDish()
{
Thread.Sleep(10 * 1000 * 60);
} /// <summary>
/// 洗衣服
/// </summary>
static void DoLaundry()
{
Thread.Sleep(25 * 1000 * 60);
}
}
ok,这里我们将大任务,拆分成了三个小任务,分别交给了三个线程去做.同时,我等待三个任务完成之后,告诉我哥们.这是整个任务的执行时间大大缩短,相当于原先一个人的活,交给了三个人干.能不快吗!
ok,到这里很多人觉得这样就行了.已经无法再继续优化了,这时候异步登场了.
(3)、异步优化
再优化代码之前,得知道线程池和CLR的概念,每个CLR会维护一个线程池.既然是池,说明线程的数量是有限的.并且我们的Web应用程序所使用的线程都会从CLR中去调取.那就说明,我们的Web程序能使用的线程有限.
ok.再回到上面的代码,

Task.WaitAll会阻塞主线程,主线程会在这里休眠,意味着这三个任务不做完,主线程会一直被占用.对应生活场景,就是我一直看着三台机器的执行,知道完成之后告诉我哥们.这期间我干不了任何事,只能看着.
那问题就大了.如果在高并发场景下.瞬时发起了1000条请求,那么就会产生非常多的等待线程,这些线程啥都不干,就干等着.造成了严重的资源浪费.显然是有问题的.
ok,异步登场了.
异步的原理(代码层面的介绍请百度),大致是这样,所有的线程不在等待,阻塞而是通过线程池调度,就是线程池主动通知.代码如下:
class Program
{
static async void Main(string[] args)
{
Console.WriteLine($"当前是我在工作");
var t1=Task.Run(() => CookRice());
var t2 = Task.Run(() => CookDish());
var t3 = Task.Run(() => DoLaundry());
Console.WriteLine($"我触发了await操作,就返回上一个调用方法去干别的事情去了,同时通过状态机机制(自行百度),这个方法会被暂停");
await Task.WhenAll(t1, t2, t3);
Console.WriteLine("await 内部操作执行完毕,线程池委派了一个新线程来执行接下去的任务,状态机机制又会恢复当前方法,接下去执行");
Console.WriteLine("哥们,搞定了,但我不是你哥们,我是你哥们的朋友");
Console.ReadKey();
} /// <summary>
/// 煮饭
/// </summary>
static void CookRice()
{
Thread.Sleep(20 * 1000 * 60);
} /// <summary>
/// 蒸菜
/// </summary>
static void CookDish()
{
Thread.Sleep(10 * 1000 * 60);
} /// <summary>
/// 洗衣服
/// </summary>
static void DoLaundry()
{
Thread.Sleep(25 * 1000 * 60);
}
}
ok,上面的代码简要的阐述了异步的原理,通过async await编程模型,当Main方法执行到await之前时,我(主线程)就会回到上一个调用方法接着执行别的任务,如果没有返回线程池.接着通过状态机机制,暂停当前方法的执行,当await方法执行完毕时,线程池会委派新的线程回来接着执行接下去的方法,再次之前状态机会恢复方法的执行.以此类推.
通过这种方式(异步),我们的Web程序就能高效率的利用好线程.
(4)、异步在磁盘IO和网络请求上面的优势
同步程序在处理磁盘IO和网络请求时,同样会采用阻塞的方式,比如发起一个后端http、webscoket请求(使用同步方法)、文件读写请求等等,那么主线程等等到远程主机和硬件设备响应之后接着执行,期间他不会返回,会一直等.那么这和上面的问题是一样的了.这就是所谓处理IO-Bound Operation的方式,很显然,这也是一个异步操作。当我们希望进行一个异步的IO-Bound Operation时,CLR会(通过Windows API)发出一个IRP(I/O Request Packet)。当设备准备妥当,就会找出一个它“最想处理”的IRP(例如一个读取离当前磁头最近的数据的请求)并进行处理,处理完毕后设备将会(通过Windows)交还一个表示工作完成的IRP。CLR会为每个进程创建一个IOCP(I/O Completion Port)并和Windows操作系统一起维护。IOCP中一旦被放入表示完成的IRP之后(通过内部的ThreadPool.BindHandle完成),CLR就会尽快分配一个可用的线程用于继续接下去的任务。这种做法的需要一个重要条件,这就是发出用于请求的IRP的操作能够立即返回,并且这个IO操作不会使用任何线程。而此时,这种异步调用是真正地在节省资源,因为我们可以腾出线程用来处理其他任务了,但是这种做法据说需要操作系统和设备的支持,但是我实际测试发现使用异步Api的收益明显要高于同步.
2、总结
综上所述,异步的优势已经非常明显了,并且Web开发,基本都是要么和tcp要么和磁盘打交道.所以用异步个人认为是最佳实践.
.Net技术栈下的异步,你还在用同步方式进行开发吗?的更多相关文章
- 快速了解Scala技术栈
http://www.infoq.com/cn/articles/scala-technology/ 我无可救药地成为了Scala的超级粉丝.在我使用Scala开发项目以及编写框架后,它就仿佛凝聚成为 ...
- 【Scala】Scala技术栈
快速了解Scala技术栈 我无可救药地成为了Scala的超级粉丝.在我使用Scala开发项目以及编写框架后,它就仿佛凝聚成为一个巨大的黑洞,吸引力使我不得不飞向它,以至于开始背离Java.固然Java ...
- 前后端分离,我怎么就选择了 Spring Boot + Vue 技术栈?
前两天又有小伙伴私信松哥,问题还是职业规划,Java 技术栈路线这种,实际上对于这一类问题我经常不太敢回答,每个人的情况都不太一样,而小伙伴也很少详细介绍自己的情况,大都是一两句话就把问题抛出来了,啥 ...
- 如何使用Microsoft技术栈
Microsoft技术栈最近有大量的变迁,这使得开发人员和领导者都想知道他们到底应该关注哪些技术.Microsoft自己并不想从官方层面上反对Silverlight这样的技术,相对而言他们更喜欢让这种 ...
- “MEAN”技术栈开发web应用
“MEAN”技术栈开发web应用 上一篇我们讲了如何使用angular搭建起项目的前端框架,前端抽象出一个service层来向后端发送请求,后端则返回相应的json数据.本篇我们来介绍一下,如何在no ...
- Vuejs技术栈从CLI到打包上线实战全解析
前言 本文是自己vue项目实践中的一些总结,针对Vue2及相关技术栈,实践中版本为2.3.3. 开发前须知 vue-cli 在开发前,我们要至少通读一遍vue官方文档和API(看官方文档是最重要的,胜 ...
- Elastic 技术栈之 Logstash 基础
title: Elastic 技术栈之 Logstash 基础 date: 2017-12-26 categories: javatool tags: java javatool log elasti ...
- 重谈react优势——react技术栈回顾
react刚刚推出的时候,讲react优势搜索结果是几十页. 现在,react已经慢慢退火,该用用react技术栈的已经使用上,填过多少坑,加过多少班,血泪控诉也不下千文. 今天,再谈一遍react优 ...
- java十年技术栈[总结复习用]
以下摘自http://www.tvtv223.com/so/8/default/8.html#36-数据库的分库分表mycat java技术栈 参考了众多资料,这里就不再详细列举了,可以自行去搜索 1 ...
随机推荐
- [ABP教程]第五章 授权
原文档 地址: Web Application Development Tutorial - Part 5: Authorization 关于此教程 在这个教程系列中,您将构建一个基于ABP的Web应 ...
- 数据仓库组件:HBase集群环境搭建和应用案例
本文源码:GitHub || GitEE 一.Hbase简介 1.基础描述 Hadoop原生的特点是解决大规模数据的离线批量处理场景,HDFS具备强大存储能力,但是并没有提供很强的数据查询机制.HBa ...
- CS系统中分页控件的制作
需求:在一个已有的CS项目(ERP中),给所有的列表加上分页功能. 分页的几个概念: 总记录数 totalCount (只有知道了总记录数,才知道有多少页) 每页记录数 pageSize (根据总 ...
- [C#] 老古董的 Microsoft Chart Controls 也可以进行数据预测
我要先声明,这篇文章介绍到的内容虽说不是不能用,但玩乐成分居多,大家看看就好,不要太认真. 1. Microsoft Chart Controls 中的 FinancialFormula 在上一篇文章 ...
- 一些JavaSE学习过程中的思路整理(主观性强,持续更新中...)
目录 一些JavaSE学习过程中的思路整理(主观性强,持续更新中...) Java书写规范 IDEA的一些常用快捷键 Java类中作为成员变量的类 Java源文件中只能有一个public类 Java中 ...
- spring boot gateway 过滤器的执行顺序
前言 学习官方文档,发现对于过滤器有分为三类 默认过滤器 自定义过滤 全局过滤器 于是就有一个疑问,关于这些过滤器的访问顺序是怎样的,今天就以一个demo来进行测试 准备阶段 过滤器工厂类 以此为模板 ...
- nginx日志按天切割
要求:以天为单位进行日志文件的切割,如host.access_20150915.log, 日志保留最近10天的, 超过10天的日志文件则进行删除. nginxcutlogs.sh脚本内容: #!/bi ...
- 【Java】流程控制 - 顺序结构、 选择(分支)结构(单分支、双分支、多分支、嵌套)、循环结构(for、while、do...while)、跳转语句(break、continue)
流程控制语句结构 文章目录 流程控制语句结构 一. 顺序结构 1. 输出语句 2. 输入语句 3.code 二.复合语句 三. 分支结构 1. 条件判断 1.单分支结构 2.双分支结构 3.多分支结构 ...
- 【Spring Boot】创建一个简单的Spring Boot的 Demo
走进Spring Boot 文章目录 走进Spring Boot 环境搭建 新建Spring Boot项目 开始创建项目 配置JDK版本 和 Initializr Service URL 配置Proj ...
- 摆脱 996——GitHub 热点速览 v.21.03
作者:HelloGitHub-小鱼干 Twitter 有位程序员总结了本周的 GitHub 中文程序员的看点:国内程序员日常--考公务员.996.抢茅台.刷算法.整健康码.在本期热点速览里,小鱼干收录 ...