,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程 Git git rebase和merge的区别 Rebase...初始化完后,主线程就进入到一个事件循环函数,主要会做以下事情: 首先,先调用处理发送队列函数,看是发送队列里是否有任务,如果有发送任务,则通过 write 函数将客户端发送缓存区里的数据发送出去,如果这一轮数据没有发送完...-> 将客户端对象添加到发送队列 -> 将执行结果写到发送缓存区等待发送; 如果是写事件到来,则会调用写事件处理函数,该函数会做这些事情:通过 write 函数将客户端发送缓存区里的数据发送出去,如果这一轮数据没有发送完...,所以如果写入 RDB 文件的时间太长,会阻塞主线程; 执行了 bgsave 命令,会创建一个子进程来生成 RDB 文件,这样可以避免主线程的阻塞; Redis的ZSet底层实现 Zset 类型的底层数据结构是由压缩列表或跳表实现的...如果对热点数据设置过期时间,活动结束后删除可能会阻塞主线程,怎么解决?
2.1 创建 我们创建了两个函数,并将两个都放在主函数里面执行,我们来看看执行的结果。...从执行结果来看我们work_a 已经执行在另外一个进程中了,work_b 和 主函数 的 函数id 是一样的, 说明它们实在同一个进程中的。...函数名 介绍 参数 返回值 Pool 进程池创建 Processcount 进程池创建 apply_async 任务加入进程池(异步) 参数 无 close 关闭进程池 无 无 join 等待进程池任务结束...(target,args) done 线程池中的某个线程是否完成了任务 done() result 获取当前线程执行任务的结果 result() 上代码 7、异步 要了解异步,我们就要只要什么是同步...而异步不需要这样,2不需要等1执行2完,它就可以进入执行状态,而且就算其中有一个发生了阻塞,后面的也不会受到影响,听来是不是优点类似与多进程和多线程?
首先,我们自己如果好好想想,如果让我们来做一个异步启动框架,需要考虑哪些问题?...多线程管理 任务的优先级 任务之间的先后关系 任务是否需要在主线程执行 多进程处理 就让我们带着这些问题去看看Alpha的内部源码。...这是因为从执行角度看,一个任务序列必须有一个开始节点和一个结束节点。但是实际情况中,可能会有多个任务可以同时开始,而且有多个任务可以同时作为结束点。...如果是需要在主线程执行的任务,就会通过Handler(sHandler)将事件传递给主线程执行。如果是需要在非主线程执行的任务,就会通过线程池(sExecutor)去执行线程任务。 诶,好像没了?...Task4是Task2和Task3的紧后任务,所以在Task2执行完之后,还要判断Task3是否执行成功,然后才能执行Task4,这就是紧前任务列表的作用。
将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中再由JavaScript引擎执行。...解释,由上图我们可以大致了解到JS引擎维护了一个任务执行栈,JavaScript是严格按照以下的顺序进行执行:主代码块入任务执行栈,JS引擎依次遍历任务执行栈的任务并执行,判断是否同步任务,如果是同步任务就立即执行...第二轮loop,执行完children2之后,由于会切换宏任务即进入另外一块代码,所以JS引擎会检查是否有残留微任务未执行,检查到children3所属微任务未执行,再切换到下一个宏任务之前会先清空微任务队列...await表达式会暂停整个async函数的执行进程并出让其控制权,只有当其等待的基于promise的异步操作被兑现或被拒绝之后才会恢复进程。promise的解决值会被当作该await表达式的返回值。...在每次事件循环运行之间,Node.js 会检查它是否正在等待任何异步 I/O 或 timers,如果没有,则将其干净地关闭。
使用setTimeout的一些注意事项 如果当前任务执行过久,会影响定时器任务的执行。 如果setTimeout存在嵌套调用,那么系统会设置最短时间间隔为4ms。...同步回调和异步回调 将一个函数作为参数传递给另一个函数 ,这个作为参数的函数就叫做回调函数。 若回调函数在主函数返回之前执行的,我们把这个回调过程称为同步回调。...把这种回调函数在主函数外部执行的过程称为异步回调。 异步回调过程 第一种是把异步函数做成一个任务,添加到消息对了尾部。...微任务 微任务就是一个需要异步执行的一个函数,执行时机是在主函数执行完毕之后、当前宏任务结束之前。...,如果遇到yield关键字,那么JS引起会返回该关键字后面的内容给外部,并暂停该函数的执行,如果遇到return关键字,JS引擎会结束该生成函数,并将return后面的内容进行最后的返回。
浏览器是多线程的,JS是单线程的(浏览器只分配一个线程来执行JS) 进程大线程小:一个进程中包含多个线程,例如在浏览器中打开一个HTML页面就占用了一个进程,加载页面的时候,浏览器分配一个线程去计算...异步:在主栈中执行一个任务,但是发现这个任务是一个异步的操作,我们会把它移除主栈,放到等待任务队列中(此时浏览器会分配其它线程监听异步任务是否到达指定的执行时间),如果主栈执行完成,监听者会把到达时间的异步任务重新放到主栈中执行...的时候,此时是异步操作,会先执行then/catch等,当主栈完成后,才会再去调用resolve/reject把存放的方法执行 - process.nextTick (node中实现的api...:执行SEND后,有一个线程是去请求数据,主栈会空闲下来 // 放等待区之前状态是1 xhr.onreadystatechange = () => { console.log(xhr.readyState...);//=> 2 3 4 }; // 主栈又空闲了 // 状态为2 把函数执行 // 状态为3 把函数执行 // 状态为4 把函数执行
因此聪明的程序员将任务分为两类:1)同步任务 2)异步任务 一张图表示事件循环 #1.同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。...js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。..., 3.执行完微任务后在拿取第一个先到达执行条件的宏任务来执行, 4.执行完后再去等待任务队列中清理执行完所有已到达执行条件的微任务, 5.然后再拿取下一个宏任务来执行,如果宏任务执行产生微任务或者微任务执行产生宏任务就一样加入到等待任务队列中...(4)主代码块(宏任务)输出4 (5)主线进程所有代码执行结束。先从微任务queue里拿回掉函数,输出3微任务全部完成 (6)再从宏任务的queue拿函数。...如果出现两个这种微任务,则先出现的会先执行 async 函数中,遇到 await 会跳出当前函数,并让出线程,再将await后面的代码放到 微任务(microtask)队列中
请求线程 在XMLHttpRequest在连接后是通过浏览器新开一个线程请求 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中再由JavaScript引擎执行...再接着执行console.log('我是同步任务2') 至此主线程执行栈中执行完毕,JS引擎线程已经空闲,开始向事件触发线程发起询问,询问事件触发线程的事件队列中是否有需要执行的回调函数,如果有将事件队列中的回调事件加入执行栈中...,定时结束就把回调扔给事件触发线程 异步http请求线程只管理http请求同样不关心结果,请求结束把回调扔给事件触发线程 事件触发线程只关心异步回调入事件队列 而我们JS引擎线程只会执行执行栈中的事件,...执行栈中的代码执行完毕,就会读取事件队列中的事件并添加到执行栈中继续执行,这样反反复复就是我们所谓的事件循环(Event Loop) 图解 首先,执行栈开始顺序执行 判断是否为同步,异步则进入异步线程...,每当指定的事件完成时,Event Table会将这个函数移到Event Queue中 当主线程内的任务执行完毕,主线程为空时,会检查微任务的Event Queue,如果有任务,就全部执行,如果没有就执行下一个宏任务
初始化完后,主线程就进入到一个事件循环函数,主要会做以下事情: 首先,先调用处理发送队列函数,看是发送队列里是否有任务,如果有发送任务,则通过 write 函数将客户端发送缓存区里的数据发送出去,如果这一轮数据没有发送完...信号函数执行完后,主进程就可以继续像往常一样处理命令了。...,所以如果写入 RDB 文件的时间太长,会阻塞主线程; 执行了 bgsave 命令,会创建一个子进程来生成 RDB 文件,这样可以避免主线程的阻塞; Redis 还可以通过配置文件的选项来实现每隔一段时间自动执行一次...执行 bgsave 命令的时候,会通过 fork() 创建子进程,此时子进程和父进程是共享同一片内存数据的,因为创建子进程的时候,会复制父进程的页表,但是页表指向的物理内存还是一个,此时如果主线程执行读操作...但是,主服务器并不会等到从服务器实际执行完命令后,再把结果返回给客户端,而是主服务器自己在本地执行完命令后,就会向客户端返回结果了。
在程序运行结束后,再把进程销毁,然后运行下一个程序,周而复始。 进程在程序运行中是非常占用资源的,无论是否会用到全部的资源,只要程序启动了,就会被加载到进程中。...待资源用完,线程就会被销毁。 线程要比进程轻量级很多。一个进程至少包含一个线程。如果一个进程只包含一个线程,那么它里面的所有代码都只会被串行地执行。...每个进程的第一个线程都会随着该进程的启动而被创建,它们被称为其所属进程的主线程。同理,如果一个进程中包含多个线程,那么其中的代码就可以被并发地执行。...一旦主 goroutine 中的代码(也就是 main 函数中的那些代码)执行完毕,当前的 Go 程序就会结束运行。当 Go 程序结束运行时,无论其他的 goroutine 是否运行,都不会被执行了。...所以,在执行完这条 Go 语句之后,主 goroutine 中的代码就执行完了,Go 程序会立即结束运行。因此前面的代码不会有任何内容被打印输出。
当事件循环处理定时器阶段的时候,Node.js会遍历js二叉堆,然后拿到过期的节点,再遍历过期节点中的链表,逐个判断是否需要执行回调。必要的时候调整js二叉堆和底层的超时时间。...1 异步方式 异步就是创建一个人子进程后,主进程和子进程独立执行,互不干扰。在主进程的数据结构中如图所示,主进程会记录子进程的信息,子进程退出的时候会用到。 ? 2 同步方式 ?...4 主线程在poll io阶段就会执行处理异步通信的回调,在回调里会执行pending为1的节点的回调。 下面我们来看一下线程池的实现。...我们先看一下轮询模式的实现,轮询模式比较简单,他是使用定时器实现的,Node.js会定时执行回调,在回调中比较当前文件的元数据和上一次获取的是否不一样,如果是则说明文件改变了。 ?...发起一个查找操作的时候,Node.js会往线程池提及一个任务,然后就继续处理其他事情,同时,线程池的子线程会调用库函数做dns查询,查询结束后,子线程会把结果交给主线程。这就是整个查找过程。 ?
在程序运行结束后,再把进程销毁,然后运行下一个程序,周而复始。 进程在程序运行中是非常占用资源的,无论是否会用到全部的资源,只要程序启动了,就会被加载到进程中。...待资源用完,线程就会被销毁。 线程要比进程轻量级很多。一个进程至少包含一个线程。如果一个进程只包含一个线程,那么它里面的所有代码都只会被串行地执行。...每个进程的第一个线程都会随着该进程的启动而被创建,它们被称为其所属进程的主线程。同理,如果一个进程中包含多个线程,那么其中的代码就可以被并发地执行。...一旦主 goroutine 中的代码(也就是main 函数中的那些代码)执行完毕,当前的Go 程序就会结束运行。当Go 程序结束运行时,无论其他的goroutine 是否运行,都不会被执行了。...所以,在执行完这条Go语句之后,主goroutine 中的代码就执行完了,Go 程序会立即结束运行。因此前面的代码不会有任何内容被打印输出。
异步任务必须指定回调函数,当主线程开始执行异步任务,其实就是在执行对应的回调函数。...如果主线程的所有同步任务都执行完,系统就会去读取「任务队列」上的异步任务,如果有可以执行的,就会结束等待状态,进入主线程,开始执行。...也就是说回调函数在下一个事件循环执行,setTimeout在这里将回调函数放至task列表后就结束了。...3、遇到Promise,属于「microtasks」,所以将第一个then的回调放到microtasks队列 4、执行完所有script代码后,检查microtasks队列,发现队列不为空,所以执行第一个回调函数输出...异步http请求线程 XMLHttpRequest在连通后通过浏览器新起一个线程请求 检测到状态变化时,如果有设置回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中,再由JS引擎执行。
当事件循环处理定时器阶段的时候,Node.js 会遍历 JS 二叉堆,然后拿到过期的节点,再遍历过期节点中的链表,逐个判断是否需要执行回调,必要的时候调整 JS 二叉堆和底层的超时时间。...然后主进程就在新的事件循环中执行,旧的事件循环就被阻塞了。 子进程结束的时候,新的事件循环也就结束了,从而回到旧的事件循环。 5.2 进程间通信 接下来我们看一下父子进程间怎么通信呢?...并且通知主线程。 主线程在 Poll IO 阶段就会执行处理异步通信的回调,在回调里会执行 pending 为 1 的节点的回调。 下面我们来看一下线程池的实现。...我们先看一下轮询模式的实现,轮询模式比较简单,他是使用定时器实现的,Node.js 会定时执行回调,在回调中比较当前文件的元数据和上一次获取的是否不一样,如果是则说明文件改变了。...发起一个查找操作的时候,Node.js 会往线程池提及一个任务,然后就继续处理其他事情,同时,线程池的子线程会调用底层函数做 DNS 查询,查询结束后,子线程会把结果交给主线程。
所以,这个新标准并没有改变JavaScript单线程的本质。 四. JavaScript是单线程,怎样执行异步的代码? 单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。...主线程在执行完当前循环中的所有代码后,就会到消息队列取出这条消息(也就是message函数),并执行它。到此为止,就完成了工作线程对主线程的通知,回调函数也就得到了执行。...如果一开始主线程就没有提供回调函数,AJAX线程在收到HTTP响应后,也就没必要通知主线程,从而也没必要往消息队列放消息。 用图表示这个过程就是: ?...image 从上文中我们也可以得到这样一个明显的结论,就是: 异步过程的回调函数,一定不在当前这一轮事件循环中执行。...)会更快,因为无需等渲染 也就是说,在某一个macrotask执行完后,就会将在它执行期间产生的所有microtask都执行完毕(在渲染前) 分别很么样的场景会形成macrotask和microtask
如何安全退出 当页面主线程执行完成后,确定要退出页面时,页面主线程会设置一个退出标志的变量,在每次执行完一个任务时,判断是否有设置退出标志。如有设置,就直接终端当前的所有任务,退出线程。...doWork 内部被调用,而是延迟 1 s,这种回调函数在主函数外部执行的过程为异步回调。...每个任务在执行过程中都有自己的调用栈,那么同步回调就是在当前主函数的上下文中执行回调函数,而异步回调是指在主函数之外执行,一般有两种方式: 把异步函数做成一个任务,添加到消息队列的尾部; 把异步函数添加到微任务队列中...为了协调这些任务有条不紊在主线程上执行,页面进程引入了消息队列和事件循环,渲染进程内部会维护多个消息队列,如延迟执行队列和普通消息队列。...执行时机是在主函数执行结束之后、当前宏任务结束之前执行回调函数,这种通常是以微任务形式体现 微任务就是一个需要异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前。
初始化完后,主线程就进入到一个事件循环函数,主要会做以下事情: 首先,先调用处理发送队列函数,看是发送队列里是否有任务,如果有发送任务,则通过 write 函数将客户端发送缓存区里的数据发送出去,如果这一轮数据没有发生完...信号函数执行完后,主进程就可以继续像往常一样处理命令了。...,所以如果写入 RDB 文件的时间太长,会阻塞主线程; 执行了 bgsave 命令,会创建一个子进程来生成 RDB 文件,这样可以避免主线程的阻塞; Redis 还可以通过配置文件的选项来实现每隔一段时间自动执行一次...执行 bgsave 命令的时候,会通过 fork() 创建子进程,此时子进程和父进程是共享同一片内存数据的,因为创建子进程的时候,会复制父进程的页表,但是页表指向的物理内存还是一个,此时如果主线程执行读操作...但是,主服务器并不会等到从服务器实际执行完命令后,再把结果返回给客户端,而是主服务器自己在本地执行完命令后,就会向客户端返回结果了。
当主线程执行完当前的宏任务后,就会检查是否有微任务需要执行,如果有,则先执行微任务,然后再执行下一个宏任务。...如果把一个进程看做一个小的车间,车间里有很多工人,有的负责操作机器,有的负责搬运材料,每个工人可以看做一个线程,线程可以共享进程的资源。可以说,线程是进程的最小单位,一个进程可以包含多个线程。...当执行栈的同步任务已经执行完成,此时主线程闲下来,它便会去查看任务队列是否有任务,如果有,主线程会将最先进入任务队列的任务加入到执行栈中执行,执行栈中的任务执行完了之后,主线程便又去任务队列中查看是否有任务可执行...,始终是要等待主线程已经空闲了才会去读取它,如果执行栈中的任务需要很长时间才能执行完,那任务队列中的任务只能等待。...在执行栈空的时候,主线程会从任务队列中取任务来执行,其过程如下: 1.选择最先进入队列的宏任务执行(最开始是 script 整体代码) 2.检查是否存在微任务,如果存在,执行微任务队列中得所以任务,
当使用 Everysec 策略的时候,由于是异步执行 fsync() 函数,所以大 Key 持久化的过程(数据同步磁盘)不会影响主线程。...在通过 fork() 函数创建子进程的时候,虽然不会复制父进程的物理内存,但是内核会把父进程的页表复制一份给子进程,如果页表很大,那么这个复制过程是会很耗时的,那么在执行 fork 函数的时候就会发生阻塞现象...在主从架构中,要适当调大 repl-backlog-size,避免因为 repl_backlog_buffer 不够大,导致主节点频繁地使用全量同步的方式,全量同步的时候,是会创建 RDB 文件的,也就是会调用...会有两个阶段会导致阻塞父进程(主线程): 创建子进程的途中,由于要复制父进程的页表等数据结构,阻塞的时间跟页表的大小有关,页表越大,阻塞的时间也越长; 创建完子进程后,如果父进程修改了共享数据中的大 Key...或者,定时检查 Redis 是否存在大 key ,如果该大 key 是可以删除的,不要使用 DEL 命令删除,因为该命令删除过程会阻塞主线程,而是用 unlink 命令(Redis 4.0+)删除大 key
事件触发线程管理一个 任务队列,异步任务触发条件达成,将回调事件放到 任务队列中 执行栈中所有同步任务执行完毕,此时JS引擎线程空闲,系统会读取 任务队列,将可运行的异步任务回调事件添加到 执行栈中,..., 本身是同步任务,而其中的回调函数才是异步任务。...当我们的同步任务执行完, JS引擎线程会询问 事件触发线程,在 事件队列中是否有待执行的回调函数,如果有就会加入到执行栈中交给 JS引擎线程执行 用一张图来解释: ?....get('www.xxxx.com',httpCallback); // 同步任务 console.log('world'); //... // 所有同步任务执行完后 // 询问事件触发线程在事件事件队列中是否有需要执行的回调函数...什么是微任务 我们已经知道 宏任务结束后,会执行渲染,然后执行下一个 宏任务, 而微任务可以理解成在当前 宏任务执行后立即执行的任务。
领取专属 10元无门槛券
手把手带您无忧上云