js 单线程 异步

线程与进程:

进程是系统资源分配和调度的单元。一个运行着的程序就对应一个进程。在windows中,每一个打开的运行的应用程序或后台程序,比如运行中的qq,谷歌浏览器,网易云音乐,资源管理器等都是一个进程。一个进程包括了运行中的程序和程序所使用到的内存和系统资源。比如,边听音乐,边在博客园写博客,这 就是开了两个进程。

线程是进程下的执行者,一个进程至少会开启一个线程(主线程),也可以开启多个线程。比如网易云一遍播放音乐,一遍显示歌词,网易云是进程,播放音乐和展示歌词是网易云进程下的两个线程。

同步和异步:

同步异步是指程序的行为。同步时程序发出调用的时候,一直等待直到返回结果。没有结果之前不会返回。也就是说,同步是调用者主动等待调用的过程。

异步是发出调用之后,马上返回,但是不会马上返回结果。调用者不必主动等待,当被调用者得到结果之后会主动通知调用者。

上面的概念可能比较官方,不易理解。通俗来说,就是,你去卖煎饼,然后再那等老板做好之后递给你,你才能走的过程 就是同步。你去肯德基点餐,然后点完之后,找个位置坐着玩手机,等做好后之后,前台的小哥哥小姐姐的叫号通知你去拿的过程就是异步。同步就是 只能一件件的事情去做,做完一件,再做一件。而异步不是,异步是你再做一件事的等待过程中,可以去做其他的事情。这就是同步和异步的区分。

console.log(1)
console.log('同步')
console.log(2)
//1
//同步
//2
console.log(1)
setTimeout(() => {console.log('异步‘)}, 0)
console.log(2)
//1
//2
//异步

浏览器是单线程还是多线程?---多线程

一个浏览器通常有以下几个常驻的线程:

- 渲染引擎线程:顾名思义,该线程负责页面的渲染。

- JS引擎: 负责JS的解析和执行

- 定时触发器线程: 处理定时事件,比如setTimeout,setInterval

- 事件触发线程:处理DOM事件

- 异步http请求线程:处理http请求

浏览器只分配给Js一个主线程,用来执行任务,但是一次只能执行一个任务,这些任务形成一个任务队列排队等候执行,但是,前端的某些任务是很消耗时间的,如果,让他们和别的任务一样,都老老实实的排队等待执行,执行效率就会非常的低,甚至导致页面的假死。所以,浏览器为了这些耗时任务,就开辟了另外的线程,如: http请求,浏览器定时触发器等,这些任务 都是异步的,

 那js 的单线程和异步 是不是有点自相矛盾呢?单线程和异步确实不能同时为一个语言的特性,js 选择了成为单线程语言,所以它本身不可能是异步的,但Js的宿主浏览器,Node等是多线程的,宿主环境通过某种方式使得Js具备了异步的属性。

任务队列

js任务分为同步任务和异步任务,同步任务指的是,在主线程上排队执行的任务,只有钱一个任务执行完毕,才能执行后一个任务。异步任务:不进入主线程,而进入“任务对列”的任务,只有“任务队列”通知主线程,某个异步任务可以执行了。该任务才会进入主线程执行。

异步执行的运行机制:

- 所有的同步任务都在主线程上,形成一个【执行栈】

- 主线程之外,还存在一个“任务队列”。只要异步任务有了运行结果,就在“任务队列”之中放置一个事件。

- 一旦“执行栈”种的所有同步任务执行完毕,系统就会读取“任务队列”,看看里面有哪些事件,那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

- 主线程不断重复上面的第三步。

回调函数

当主线程开始执行异步任务,就是执行对应的回调函数。

异步任务必须指定回调函数。

js中的异步之定时器

setTimeout(function(){
  console.log(0);
},0)
 
console.log(1);
//1
//0

当有耗时任务的时候,会把它放在任务队列中等待主线程空闲然后再执行。实际再执行的过程中,浏览器会默认setTimeout以及ajax请求这一类的方法都是耗时程序(尽管可能不耗时)。所以此时的setTimeout尽管它推迟时间为0,但是js不会立即执行,而是把它加入任务队列,当执行完执行栈的同步任务也就是打印1后,再执行setTimeout的回调函数,打印0。

setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行。划重点::: 尽早可能。也就是说setTimeout 将当前的回调函数加入到任务队列中,当前任务耗时过长,需要等很久,灭有办法保证,回调函数会在指定的时间内执行。

猜你喜欢

转载自www.cnblogs.com/mn6364/p/10940102.html