node特点:
1. 异步单线程:
我们知道php和java这些后端语言是多线程 但为什么node却采用了异步单线程呢 这样做的好处是什么呢
优点:
- 节约服务器内存(线程越多占用的内存越多)
- 节约上下文切换的时间(由于多线程实现原理是通过切换时间片来实现的 所以线程越多 需要切换的次数就越多 耗费的时间越长)
- 不存在锁的问题 (java通常会通过给进程加锁来解决多个线程访问同一资源的问题 而单线程就不存在这个问题)
2. 非阻塞:
有些朋友第一次接触这个词汇可能分不清阻塞和同步,非阻塞和异步的区别,下面我就简单分享一下我对这些的理解:
同步和异步起决于被调用者
阻塞和非阻塞起决于调用者
可能这样说有点模糊 接下来我以一个简单的例子来解释:
你向你仰慕多年的女孩表白,女孩是里面给你答复还是考虑一段时间后给你答复,这里的女孩就是被调用者 立即给你答复就是同步 考虑一段时间后给你答复就属于异步 而阻塞和非阻塞起决于你 也就是调用方 在女孩回答你之前你是继续干别的事还是一直等待女孩答复就是阻塞和非阻塞
3. 常见的线程:
既然说到了线程 就简单说一下常见的线程(浏览器)
- js线程
- ui线程(和js线程互斥 两者只有一者正在执行 不会同时进行)
- 浏览器事件触发线程
- 定时器触发线程
- 异步http请求线程
4. 浏览器中的event loop
heap堆:存放引用类型的数据
stack栈:存放基本类型的数据和引用类型的指针 也是任务执行的地方 先进后出(执行栈)
callback queue任务队列:存放异步任务 先进先出
js在执行栈中执行js代码, 在没有遇到同步任务之前按js顺序依次执行 ,当碰到异步任务(定时器 ajax)时, 会把该任务分配给对应的线程(定时器触发线程 异步http请求线程),不同线程开始执行被分配的任务, 当线程处理完成后(定时器时间到了 ajax请求到数据)会把该任务依次放入任务队列
最后当执行栈stack中的任务执行完成之后 任务队列中的任务(异步任务)就会放到执行栈依次执行 如果从任务队列中拿到的任务中还存在异步任务 又会执行与原来相同的操作 无限循环 这就是event loop
注意:只有执行栈中的任务被执行完任务队列中的任务才会放到执行栈中执行,这也是为什么异步任务永远在同步任务之后执行的原因
5.node中的事件循环
- v8引擎解析执行js脚本
- 解析代码后,调用node API
- libuv库负责node API的执行 它将不同的任务分配给不同的线程 形成一个event loop 以异步的方式将任务的执行结果返回给v8引擎
- v8 引擎返回给用户
总结:node内部通过同步的方式实现异步
例子:我打电话问图书馆的管理员问有没有高程3 然后图书馆管理员挂掉了电话开始一个一个书柜寻找高程3 一段时间后打电话回来告诉我结果 在管理员找书期间我任然可以做其他事情