那些年我们一起追逐的多线程(Thread、ThreadPool、委托异步调用、Task/TaskFactory、Parallerl、async和await)
一. 背景
在刚接触开发的头几年里,说实话,根本不考虑多线程的这个问题,貌似那时候脑子里也有没有多线程的这个概念,所有的业务都是一个线程来处理,不考虑性能问题,当然也没有考虑多线程操作一条记录存在的并发问题,后面随着处理的系统业务越来越复杂,多线程再也回避不了了,也就借此机会深入研究了一下.Net中的多线程的处理方案。
发现在.Net领域中,多线程的处理大致经历了这么几个阶段:Thread→ThreadPool→委托的异步调用→Task→TaskFactory→Parallerl→异步编程模型(async和await)。
关注我博客的人会发现,早在2017年6月份的时候,就开始整理多线程问题了,大约用了6篇文章的来介绍了.Net中的线程的使用方法,主要是介绍相应类的实例方法的使用,有点帮助文档的意思了哦,最近多线程使用的相当频繁,借此机会重新结合一些实际业务系统介绍一下.Net领域的多线程问题,本次将整合原先的六篇文章(删除或覆盖更新)。
本质: 充分发掘CPU的性能,把一些并没有先后强依赖关系、且耗时代码块放到一个新的线程里去处理,那么原先按顺序执行的业务就会变成并行执行,让主线程继续往后执行,节约了时间了,提高了效率。
下面补充一下多线程在时间和空间上的开销:
(一). 时间上:
①:开启或销毁一个线程都会通知进出中的dll程序集,让这些dll进行相应的操作。
②:时间片切换:4个逻辑处理器(不考虑Inter的超线程技术,一核对多个线程),同时并行只能处理4个线程,多余的休眠,很多时候,我们看似很多线程在并行执行,实际上是间歇性的串行。
《关于这个说法有异议的话,请留下您的见解,欢迎讨论,请勿谩骂》
(二). 空间上:
①:用户模式堆栈,一个线程分配1M的堆栈空间。
②:内核模式的堆栈,用户模式的参数需要传递到内核模式。
③:线程的内核数据结构,会存放一下变量。
二. 概念的梳理
1. 进程、线程和多线程
进程:当一个程序开始运行时,它就是一个进程(或者多个,eg:游戏),进程包括运行中的程序和程序所使用到的内存和系统资源,而一个进程又是由多个线程组成。
线程:线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。
多线程:多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
2. 多线程的好处和弊端
好处:可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。(牺牲空间资源,来换取时间)
弊端:
①:线程也是程序,所以线程需要占用内存,线程越多占用内存也越多;(占内存多)
②:多线程需要协调和管理,所以需要CPU时间跟踪线程; (占cpu多)
③:线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;(多线程存在资源共享问题)
④:线程太多会导致控制太复杂,最终可能造成很多Bug。(管理麻烦,产生意外bug)
3. 何时建议使用多线程
①. 当主线程试图执行冗长的操作,但系统会卡界面,体验非常不好,这时候可以开辟一个新线程,来处理这项冗长的工作。
②. 当请求别的数据库服务器、业务服务器等,可以开辟一个新线程,让主线程继续干别的事。
③. 利用多线程拆分复杂运算,提高计算速度。
4. 何时不建议使用多线程
当单线程能很好解决,就不要为了使用多线程而用多线程。
5. 同步调用和异步调用
①单线程同步调用:方法从上而下一次执行,一步一步执行,有先后顺序。
②异步调用(区别于异步方法):开启新的线程去执行业务,主线程单独执行,可以选择是否等待子线程执行完后再执行
同步方法 VS 异步方法:
1. 一个误区:异步方法指的是一些特有的方法(并不开启新线程),它和开启一个新的线程比如“很多情况下我们会说,开启一个新的线程去异步调用”,这不是一回事,典型的异步方法,比如js 的ajax请求。
2. 同步方法:我们平时封装的一些普通方法大多数都是同步方法,同步方法典型的特点:就是在没有得到方法的返回值或者该方法没有执行完,该调用就需要在这等待,不能继续执行。
3. 异步方法:异步方法在调用后,调用这在没有得到返回结果前,就可以继续执行后续业务,异步方法通常是通过通知、回调的方式告诉调用者,无须消耗过多的性能。
举例1:
$.Post("url",{},function(data){ });
$("#div1").html("");
这两行代码,第一行发送异步请求的时候,即使得到回调返回值,下面清空div1内容的操作同样也将执行,Post就是异步方法。
举例2:
先封装1个方法: function Add(a,b){ 先休眠5s; return a+b}
调用:
Add(1,2);
$("#div1").html("");
这两行代码,Add方法就属于同步方法,所以必须等5s后,Add方法执行完,才能执行下面清空div1内容的操作。
总结:同步方法和异步方法的区别就是:是否需要等待返回结果,才能执行后续操作。
6. 异步多线程的三个特点
①:同步方法卡界面,原因是主线程被占用;开启新线程去异步调用不卡界面,原因是计算交给了别的线程,主线程空闲.
②:同步方法慢,原因是只有一个线程计算;开启新线程去异步调用快,原因是多个线程同时计算,但是更消耗资源,不宜太多.
②:异步多线程是无序的,启动顺序不确定、执行时间不确定、结束时间不确定.
三. 系列章节
第一节:复习委托,并且通过委托的异步调用开启一个新线程和异步回调、异步等待。
第三节:ThreadPool的线程开启、线程等待、线程池的设置、定时功能。
第四节:Task的启动的四种方式以及Task、TaskFactory的线程等待和线程延续的解决方案。
第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。
第六节:深入研究Task实例方法ContinueWith的参数TaskContinuationOptions。
第七节:利用CancellationTokenSource实现任务取消和利用CancellationToken类检测取消异常。
第八节:Task的各类Task<TResult>返回值以及通用线程的异常处理方案。
第九节:深究并行编程Parallel类中的三大方法 (For、ForEach、Invoke)和几大编程模型(SPM、APM、EAP、TAP)
第十节:利用async和await简化异步编程模式的几种写法
第十一节:深究用户模式锁的使用场景(异变结构、互锁、旋转锁)
第十二节:深究内核模式锁的使用场景(自动事件锁、手动事件锁、信号量、互斥锁、读写锁、动态锁)
第十三节:实际开发中使用最多的监视锁Monitor、lock语法糖的扩展、混合锁的使用(ManualResetEvent、SemaphoreSlim、ReaderWriterLockSlim)
第十四节: 介绍四大并发集合类并结合单例模式下的队列来说明线程安全和非安全的场景及补充性能调优问题。
第十五节:深入理解async和await的作用及各种适用场景和用法
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,如需代码请加我QQ:604649488 (备注:评论的博客名)
那些年我们一起追逐的多线程(Thread、ThreadPool、委托异步调用、Task/TaskFactory、Parallerl、async和await)的更多相关文章
- c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习
c#中@标志的作用 参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...
- 异步和多线程,委托异步调用,Thread,ThreadPool,Task,Parallel,CancellationTokenSource
1 进程-线程-多线程,同步和异步2 异步使用和回调3 异步参数4 异步等待5 异步返回值 5 多线程的特点:不卡主线程.速度快.无序性7 thread:线程等待,回调,前台线程/后台线程, 8 th ...
- .net 多线程 Thread ThreadPool Task
先准备一个耗时方法 /// <summary>/// 耗时方法/// </summary>/// <param name="name">< ...
- 异步多线程 Thread ThreadPool Task
一.线程 Thread ThreadPool 线程是Windows任务调度的最小单位,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针.程序计数器等),但代码区是共享的,即不同的线程可以 ...
- .NET多线程(Thread,ThreadPool,Task,Async与Await)
.NET多线程是什么? 进程与线程 进程是一种正在执行的程序. 线程是程序中的一个执行流. 多线程是指一个程序中可以同时运行多个不同的线程来执行不同的任务. .NET中的线程 Thread是创建和控制 ...
- C#委托异步调用
参考页面: http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html http://www.yuanjiaocheng.net/w ...
- 委托-异步调用-泛型委托-匿名方法-Lambda表达式-事件【转】
1. 委托 From: http://www.cnblogs.com/daxnet/archive/2008/11/08/1687014.html 类是对象的抽象,而委托则可以看成是函数的抽象.一个委 ...
- 多线程编程学习笔记——异步调用WCF服务
接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...
- 多线程Thread,线程池ThreadPool
首先我们先增加一个公用方法DoSomethingLong(string name),这个方法下面的举例中都有可能用到 #region Private Method /// <summary> ...
随机推荐
- pyspider爬网页出现中文乱码的解决办法
为什么会出现乱码呢?按照binux的说法 这就是 lxml 的蛋疼之处,给它 unicode 它有的时候它不认,给它 bytes 它又处理不好 方法1: response.content = (res ...
- SQLServer之数据库行锁
行锁使用注意事项 1.ROWLOCK行级锁确保在用户取得被更新的行,到该行进行更新,这段时间内不被其它用户所修改.因而行级锁即可保证数据的一致性,又能提高数据操作的并发性. 2.ROWLOCK告诉SQ ...
- java 根据ip获取地区信息(淘宝和新浪)
package com.test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStr ...
- Linux:Day17(下) openssl
Linux Services and Security OpenSSL OpenSSH dns:bind web:http,httpd(apache),php,mariadb(mysql) lamp ...
- 《css世界》笔记之流、元素与基本尺寸
1. 块级元素 基本特性:就是一个水平流上只能单独显示一个元素,多个块级元素则换行显示. 块级元素和"display 为block 的元素"不是一个概念,display:list- ...
- [kuangbin带你飞]专题二十二 区间DP-B-LightOJ - 1422
题意大概是这样,第i天必须穿a[i](某一种类)的衣服,你可以套着穿很多件,对于第i天,你有两种操作,一种是脱掉现在的衣服,一种是穿上新的一件,但是你脱掉的衣服,以后不能再穿.问最少需要多少件衣服? ...
- 初识Haskell 二:基本操作符、类型Type、数据结构
对Discrete Mathematics Using a Computer的第一章Introduction to Haskell进行总结.环境Windows 1. 在安装了ghci后,便可以进行Ha ...
- Photoshop快速给美女人像换头发
今天给大家带来的教程是应用PS来抠出人物图片的发丝和修改头发的颜色. OK开始今天的教程 1.将素材文件拖拽进PS,CTRL+J复制一层. 2.应用快速选择工具大致的将头发部分选区出来,不需要太过仔细 ...
- Go 目录
Go语言 go语言初识 基本数据类型和操作符 字符串,时间,流程控制,函数 GOROOT,GOPATH,GOBIN,project目录 数组和切片 指针和内置函数 排序和查找 map
- beanshell断言模版
if("${createTime_1}".equals("${createTime_2}")){ Failure = false; FailureMessage ...