多线程与异步
多线程与异步不是一个概念
多线程是异步的一种实现方式
异步是最终目的
参考
一、定义:
- 同步:线程(进程)在执行过程中,按从上到下的顺序依次执行代码
- 异步:
- 彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这一事件完成后再工作。
- 调用方法的主线程干一件事的时候,不需要同步等待另一个线程完成,此时主线程可以干其他事情。
- 与任务相关
- 多线程:
- 程序设计逻辑层概念
- 具体执行者相关
- 进程中并行/并发运行的一段代码,可以实现线程间的切换执行。
- 在单核处理器上,多线程往往会给人程序是在并行执行的错觉,本质:,处理器是通过调度算法在多线程之间进行切换和调度。或者根据外部输入(中断)和线程的优先级的组合来进行线程的切换。
- 在多核处理器上,线程才是真正的并行运行。多个处理器同时执行多个线程,以达到更加高效的处理。
- 异步模型:允许同一时间发生(处理)多个事件。程序调用一个耗时较长的功能(方法)时,它并不会阻塞程序的执行流程,程序会继续往下执行。当功能执行完毕时,程序能够获得执行完毕的消息或能够访问到执行的结果(如果有返回值或需要返回值时)
- 异步编程设计:
- 针对耗时性功能,提供方法/函数
- 函数的参数中包含一个额外的参数,用于回调。
- 这个函数往往称作回调函数。当比较耗时的功能执行完毕时,通过回调函数将结果返回。两个经典例子让你彻底理解java回调机制
二、举例:
情景:厨师、饭店订单、蒸鸡蛋和烤面包
- 同步:这个厨师先蒸鸡蛋,蒸鸡蛋过程中不能烤面包、也不能干别的,只能等待;
- 异步:单线程
- 先蒸鸡蛋,鸡蛋在蒸的时候,去烤面包,面包在烤的过程中,鸡蛋熟了,不管是不是在给面包切片还是在等待面包烤熟,都要先去处理鸡蛋(如把鸡蛋从锅里端上来,送给客人),然后再回来处理烤面包,面包在烤的过程中可以打扫厨房,等烤面包好的时候,再去处理烤面包(如:送给客人)
- 多线程::你雇多个厨师,一个蒸鸡蛋,另一个烤面包,你作为资源协调者,协调他们对物品的先后顺序,不让吵架(多线程的资源共享),同时你要给两个人money(多线程的性能损耗)
三、推荐:
限制分类:
- IO限制:数据传输上的数据等待,本身消耗计算量不大,重要事情不是程序完成的。如console.readkey() 网络数据下载,
- 计算限制:执行大量计算的操作
计算限制的任务:
- 多请厨师(多开线程),最好和处理器数一致,每个任务分配一个线程,一个线程一个处理器(避免上下文切换),
- 每个处理器去处理任务,这会加快任务的处理速度。
计算不限制的任务:
- 不使用多线程,单线程的task
- task的主要作用是不堵塞主线程,构建响应灵敏的程序,不一定会开辟多个线程。而多线程一定是开辟多个线程并发执行的。
- Task中再遇到Await后,方法立即返回,不会因为await关键字而阻塞当前线程,当await关键字标记的语句执行完成后才会继续执行await后面的语句。
- Task会中断方法的执行,但是不会阻塞线程,用其余的cpu片段处理别的任务。但是锁会阻塞方法所在的线程,造成活锁(基元用户模式构造造成)
推荐原则是:
客户端应用程序:用多线程方式处理计算限制的操作,用task处理IO限制的操作
服务器应用程序:始终用Task