单线程多线程
什么是线程进程?
进程:是cpu分配资源的最小单位;(是能拥有资源和独立运行的最小单位)
线程: 是cpu调度的最小单位;(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程)
比喻:进程就是一个公司,每个公司都有自己的资源可以调度;公司之间是相互独立的;而线程就是公司中的每个员工(你,我,他),多个员工一起合作,完成任务,公司可以有一名员工或多个,员工之间共享公司的空间
比喻:1万块儿砖搬上10楼,整栋楼就是进程。一个电梯运就是单线程,多个电梯一起运就是多线程.
什么是单线程多线程?
单线程:
单线程在程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行。单线程就是进程里只有一个线程。
多线程:
在单个程序中同时运行多个线程完成不同的工作,称为多线程。
浏览器是多进程的:
放在浏览器中,每打开一个tab页面,其实就是新开了一个进程,在这个进程中,还有ui渲染线程,js引擎线程,http请求线程等。 所以,浏览器是一个多进程的。
JS是单线程的:
JavaScript是单线程的,也就是说,同一个时刻,JavaScript只能执行一个任务,其他任务只能等待。
为什么JS要设计成单线程的?
JavaScript 的设计就是为了处理浏览器网页的交互(DOM操作的处理、UI动画等),决定了它是一门单线程语言。如果有多个线程,它们同时在操作 DOM,那网页将会一团糟。
这主要和js的用途有关,js是作为浏览器的脚本语言,主要是实现用户与浏览器的交互,以及操作dom;这决定了它只能是单线程,否则会带来很复杂的同步问题。 举个例子:如果js被设计了多线程,如果有一个线程要修改一个dom元素,另一个线程要删除这个dom元素,此时浏览器就会一脸茫然,不知所措。所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变
同步异步 宏任务 微任务
为什么任务要分为同步任务和异步任务?
那如果一个任务的处理耗时(或者是等待)很久的话,如:网络请求、定时器、等待鼠标点击等,后面的任务也就会被阻塞,也就是说会阻塞所有的用户交互(按钮、滚动条等),会带来极不友好的体验。
所以,又引入了异步任务。
同步任务:同步任务不需要进行等待可立即看到执行结果,比如console
异步任务:异步任务需要等待一定的时候才能看到结果,比如setTimeout、网络请求
异步任务又分为宏任务和微任务
为什么要有微任务宏任务?
有些任务优先级更高,我们js允许它插队优先执行
常见的宏任务和微任务:
// 宏任务:script 定时器 延时器(setTimeout,setInterval) ajax请求 ,dom事件
// 微任务: promise.then promise.catch
事件循环(Event Loop)与消息队列(task queue)
概念_EventLoop事件循环:
EventLoop事件循环的是在浏览器中的一个概念.浏览器中的EventLoop:js是单线程的,一次只能做一件事。js在浏览器这个宿主环境中运行。用户交互,定时器,网络请求等等浏览器中的事件会产生对应的任务,任务多了要在任务队列中排队,浏览器的主线程依次取出
任务来执行,此过程不断重复从而形成一个循环,称为eventloop。
执行顺序:
// 宏任务 微任务 如何执行的
// 1. 先执行宏任务
// 2. 当宏任务执行结束了,在执行所有的微任务(如果没有微任务,就不需要执行)
// 3. 继续执行下一个宏任务了
同步异步代码如何执行:
先把所有的同步代码添加到任务队列,排在前面,然后把异步代码排到同步代码的后面(注意如果此时,好几个异步代码都有时间,比如过几秒后再执行,那么谁先被放任务队列中,谁的等待时间短就会被先放进去)
宏任务微任务面试题:
<!-- 第一题 -->
<!-- <script>
console.log(1)
setTimeout(function () {
console.log(2)
new Promise(function (resolve) {
console.log(3)
resolve()
}).then(function () {
console.log(4)
})
})
new Promise(function (resolve) {
console.log(5)
resolve()
}).then(function () {
console.log(6)
})
setTimeout(function () {
console.log(7)
new Promise(function (resolve) {
console.log(8)
resolve()
}).then(function () {
console.log(9)
})
})
console.log(10)
</script> -->
<!-- 第二题 -->
<!-- <script>
console.log(1)
setTimeout(() => {
console.log(2)
}, 0)
console.log(3)
</script>
<script>
console.log(4)
setTimeout(() => {
console.log(5)
}, 0)
console.log(6)
</script> -->
<!-- 第三题 -->
<script>
console.log(1)
setTimeout(function () {
console.log(2)
}, 0)
const p = new Promise((resolve, reject) => {
console.log(3)
resolve(1000) // 标记为成功
console.log(4)
})
p.then((data) => {
console.log(data)
})
console.log(5)
</script>
<!-- 第四题 -->
<script>
new Promise((resolve, reject) => {
resolve(1)
new Promise((resolve, reject) => {
resolve(2)
}).then((data) => {
console.log(data)
})
}).then((data) => {
console.log(data)
})
console.log(3)
</script>
<!-- 第五题 -->
<!-- <script>
console.log(1)
async function fnOne() {
console.log(2)
await fnTwo() // 右结合先执行右侧的代码, 然后等待\
console.log(3)
// █
//await 函数()
// 其它代码
// 这里会执行这个函数,然后把这儿的其它代码放到微任务里.详见图
}
async function fnTwo() {
console.log(4)
}
fnOne() //调用才执行
setTimeout(() => {
console.log(5)
}, 2000)
let p = new Promise((resolve, reject) => {
// new Promise()里的函数体会马上执行所有代码
console.log(6)
resolve()
console.log(7)
})
setTimeout(() => {
console.log(8)
}, 0)
p.then(() => {
console.log(9)
})
console.log(10)
</script> -->
<!-- <script>
console.log(11)
setTimeout(() => {
console.log(12)
let p = new Promise((resolve) => {
resolve(13)
})
p.then((res) => {
console.log(res)
})
console.log(15)
}, 0)
console.log(14)
</script> -->
<!-- 第六题字节面试 -->
<script>
async function async1() {
console.log('1')
await async2()
console.log('2')
}
async function async2() {
console.log('3')
}
console.log('4')
setTimeout(function () {
console.log('5')
}, 0)
async1()
new Promise(function (resolve) {
console.log('6')
resolve()
}).then(function () {
console.log('7')
})
console.log('8')
</script>
注意 :
1.script最先放到宏任务
2.注意setimeout的时间谁快谁先放入宏任务
3.多个script要一开始就连着排队
\