首页 前端知识 js 多线程有几种实现方法,js如何实现多线程

js 多线程有几种实现方法,js如何实现多线程

2024-05-05 12:05:57 前端知识 前端哥 116 741 我要收藏

大家好,小编为大家解答js 多线程有几种实现方法的问题。很多人还不知道js如何实现多线程,现在让我们一起来看看吧!

一、什么是JS引擎?


1、JS内核,也称JS引擎(例如V8引擎),负责处理执行java脚本程序,
2、由于js是单线程(一个Tab页内中无论什么时候都只有一个JS线程在运行JS程序),依靠任务队列来进行js代码的执行,所以js引擎会一直等待着任务队列中任务的到来,然后加以处理。

注意,JavaScript 只在一个线程上运行,不代表 JavaScript 引擎只有一个线程python for语句用法。事实上,JavaScript 引擎有多个线程,单个脚本只能在一个线程上运行(称为主线程),其他线程都是在后台配合

二、JavaScript单线程

JavaScript是单线程指的是同一时间只能干一件事情,只有前面的事情执行完,才能执行后面的事情。导致遇到耗时的任务时后面的代码无法执行。

在此之前啊 我们必须了解同步和异步 

1. 同步任务(synchronous) 
console.log(123);

console.log(456);

for (let i = 1; i <= 5; i++) {

  console.log(i);

}

顾名思义 得到的一定是 顺序执行 

2. 异步任务(asynchronous)

setTimeout(() => {

  console.log('定时器');

}, 0)

console.log('奥特曼');

既然JS是单线程的,那怎么实现异步的呢?

单线程意味着什么:JavaScript 同时只能执行一个任务,其他任务都必须在后面排队等待。也就是说代码只能同步执行,必须执行上一行才能执行下一行。

console.log('1')
setTimeout(() => {
    console.log('2')
}, 0);
console.log('3')

按普通的执行顺序来说 定时器在上面  应该先输出定时器 在输出 奥特曼  

最后拿到的结果却先输出奥特曼 在输出了定时器  原因呢就是 setTimeout是异步任务  

补充一个知识点  setTimeout的定时器 不管延迟多少毫秒 也是异步的  每个浏览器的时间也是不同的,各个浏览器都有差异 但定义了0 最小也是4毫秒

三、任务队列(task queue)

通过上面代码知道setTimeout是异步的   我们就搞清了执行顺序优先级  同步代码>异步代码      所以说 在任务队列中 分为两大类 1.同步任务   2. 异步任务 

1.执行栈

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。

(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

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

(4)主线程不断重复上面的第三步,称为事件循环(Event Loop)。

同样都是去吃饭  但是p2 省去了出去的时间过程

简单了解后 我们再来深入了解 异步任务中的 宏任务(macrotask )和 微任务(microtask )

个人理解对于宏任务和微任务 可以理解为两种异步的形态,  异步有两个孩子 宏任务 和 微任务

宏任务中的方法:1. (可以理解为外层同步代码,作为入口 )   2. setTimeout/setInterval

微任务中的方法:1.Promise 2. nextTick

而他们的执行顺序 是 微任务 先输出 在输出 宏任务

setTimeout(() => {

  console.log('定时器');

}, 0)

new Promise((resolve) => {

  console.log('同步代码') 

  resolve('异步代码')

}).then((res) => {

  console.log(res);  

})

console.log('奥特曼');

 

注意奥 new Promise是创建一个构造函数 这个过程是同步的,而.then方法是异步的  所以代码先执行 同步>微任务>宏任务

为了更加详细 用图来描述执行过程   下面的图有一丁丁大 学习不怕费流量哦

 宏任务、微任务 执行顺序面试题
console.log('1');

setTimeout(function () {

  console.log('2');

  process.nextTick(function () {

    console.log('3');

  })

  new Promise(function (resolve) {

    console.log('4');

    resolve();

  }).then(function () {

    console.log('5')

  })

})

process.nextTick(function () {

  console.log('6');

})

new Promise(function (resolve) {

  console.log('7');

  resolve();

}).then(function () {

  console.log('8')

})

setTimeout(function () {

  console.log('9');

  process.nextTick(function () {

    console.log('10');

  })

  new Promise(function (resolve) {

    console.log('11');

    resolve();

  }).then(function () {

    console.log('12')

  })

})

答案 :

第一轮 执行外面同步代码 : 1     7   

第二轮 执行 微任务 : 6    8    

第三轮 宏任务  第一个setTimeout : 同步  2  4   微任务 3   5   第二个setTimeout:同步  9   11    微任务  10   12 

整体答案:  1、7 、6、8、2、4、3、5、9、11、10、12

四、什么是事件循环?

定义:主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。 不断重复的过程就是我们说的 Event Loop (事件循环)。

4.为什么说js是单线程?

浏览器是多进程的,浏览器每一个 tab 标签都代表一个独立的进程,其中浏览器渲染进程(浏览器内核)属于浏览器多进程中的一种,主要负责页面渲染,脚本执行,事件处理等
其包含的线程有:GUI 渲染线程(负责渲染页面,解析 HTML,CSS 构成 DOM 树)、JS 引擎线程、事件触发线程、定时器触发线程、http 请求线程等主要线程。

主线程:也就是 js 引擎执行的线程,这个线程只有一个,页面渲染、函数处理都在这个主线程上执行。

工作线程:也称幕后线程,这个线程可能存在于浏览器或js引擎内,与主线程是分开的,处理文件读取、网络请求等异步事件。

可以看出,异步操作都是放到事件循环队列里面,等待主执行栈来执行的,并没有专门的异步执行线程,所以说js是单线程

5.为什么js要是单线程?

js设计为单线程还是跟他的用途有关,试想一下 如果js设计为多线程 那么同时修改和删除同一个dom 浏览器又该如何执行?


 

转载请注明出处或者链接地址:https://www.qianduange.cn//article/6909.html
标签
PHP
评论
发布的文章

JQuery中的load()、$

2024-05-10 08:05:15

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!