一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情。
线程机制与事件机制
进程与线程
进程概念:
① 进程是程序的一次执行,它占有一片独有的内存空间
② 可以通过window任务管理器查看进程,并且各个应用程序之间的内存是相互独立的,不会轻易访问到另外一个应用程序的内存
线程概念:
① 线程是进程内的一个独立执行单元
② 是程序执行的一个完整流程
③ 是CPU的最小的调度单元
两者的关系:
① 一个进程中一般至少有一个运行的线程:主线程
② 一个进程中也可以同时运行多个线程,我们会说程序是多线程运行的
③ 一个进程内的数据可以供其中的多个线程直接共享
④ 多个进程之间的数据是不能直接共享的
浏览器运行是单进程还是多进程?
答:有些是单进程,有些是多进程。比如老板IE和火狐就是单进程的,chrome和新版IE是多进程的。
图解
如上图,我们的应用程序存储在硬盘上面,接着我们启动程序A,或者程序B
这样会启动它们对应的进程,比如这里A有3个进程,B有一个进程。
诶?一个程序能搞3个进程吗?能,点开任务管理器,以谷歌浏览器为例子的话,你会看到任务管理器中它启动了多个进程。看的出来有些程序是多进程的,有的是单进程的。
而一个进程中有些有多个线程,有些只有一个线程,它们被称为多线程程序和单线程程序。
问题: 我一个应用程序启动了多个进程,每个进程里面只有一个线程,请问这是多线程还是单线程?
答: 是单线程,所谓多线程单线程程序是局限在一个进程内。
.
相关问题
问题①: 何为多进程与多线程?
答: 多进程:一个应用程序能同时启动多个实例运行。多线程:在一个程序内,同时有多个线程在运行
问题②: 比较单线程与多线程
答: 多线程的优点:能有效提高CPU的利用率;缺点:创建多线程的开销、线程间切换的开销、死锁和状态同步问题。 单线程:优点:顺序编程简单易懂;缺点:效率低
问题③: JS是单线程还是多线程?
答: js是单线程运行的,但使用Web Worker可以多线程运行
问题④: 浏览器是单线程还是多线程?
答: 多线程,不管什么浏览器都是多线程
问题⑤: 浏览器是单进程还是多进程?
答: 有单进程也有多进程。
相关知识
① 应用程序必须运行在某个进程的某个线程上
② 一个进程中至少要有一个运行的线程,称为主线程,进程启动后自动创建
③ 一个进程中也可以同时运行多个线程,称之为多线程程序
④ 一个进程内的数据可以供其中的多个线程直接共享
⑤ 多个进程之间的数据是不能共享的
⑥ 线程池:是保存多个线程对象的容器,实现线程对象的反复利用
比如某个程序要执行,我们从线程池中拿出一个线程去执行某段程序,执行完后又把它放回线程池而不是让它成为垃圾对象,这样做是为了复用。
浏览器内核
浏览器内核是支撑浏览器运行的最核心的程序,不同浏览器的内核不一样,内核由很多模块组成。
主线程:
- JS引擎模块:负责js程序的编译与运行
- html,css文档解析模块:负责页面文本解析
- DOM/CSS模块:负责dom/css在内存中的相关处理
- 布局和渲染模块:负责页面的布局和效果的绘制(内存中的对象)
- 其他......
分线程:
- 定时器模块:负责定时器的管理
- 事件响应模块:负责事件的管理
- 网络请求模块:负责ajax请求
定时器相关问题
1.定时器真是定时执行吗?
定时器并不能保证真正定时执行
一般会延迟一点点,也有可能延迟很长时间
2.定时器的回调函数是在分线程执行吗
在主线程执行,js是单线程的
3.定时器如何实现?
涉及同步任务异步任务与事件循环模型,之前的文章也有说过。
传送入口
案例:
document.querySelector('button').onclick = function () {
var start = Date.now();
console.log('启动定时器前——————————');
setTimeout(function () {
console.log('定时器执行了:', Date.now() - start);
}, 200);
console.log('启动定时器后——————');
//做一个长时间的工作
for (var i = 0; i < 1000000000; i++) {
}
其实这就是同步与异步的结果,回调函数是一个异步任务,只有同步任务执行完才会去任务执行队列中找异步任务。
JS是单线程的
1.如何证明js执行是单线程的?
setTimeout()的回调函数是在主线程执行的
定时器回调函数只有在运行栈中的代码全部执行完后才有可能执行 (同步与异步,上面有传送入口)
2.为什么js要用单线程模式,而不用多线程?
JS的单线程,与它的用途有关
做为浏览器的脚本语言,JS的主要用途是与用户互动,以及操作DOM
这决定了它只能是单线程,否则会带来很复杂的同步问题
举个例子,我对p标签进行操作,如果是多线程,在线程1的时候,我要去更新p标签,但是恰好时间片用完了,这时候交给了线程2,线程2做了删除p标签的操作,再回去运行线程1的时候发现,p没了,只能报错了.虽然H5的js有多线程的操作,也只能有一个线程允许更新操作界面,不然代码复杂度会增加
3.代码的分类:
初始化代码(同步代码。或者说同步任务)
回调代码(异步代码,或者说异步任务)
4.js引擎执行代码的基本流程
① 先执行初始化代码:包含一些特别的代码
- 设置定时器
- 绑定监听
- 发送ajax请求
② 后面在某个时刻才会执行回调代码
(其实就是先执行同步任务,再执行异步任务)
setTimeout(function () {
console.log('time 2222');
alert('4000');
}, 4000);
setTimeout(function () {
console.log('time 1111');
alert('2000');
}, 2000);
setTimeout(function () {
console.log('time 0000');
alert('0000');
});
function fn() {
console.log('---fn()---');
}
fn();
console.log('alert之前--');
alert('---------');
console.log('alert之后--');
以下是上面代码的输出顺序:
alert的特点就是暂停当前主线程代码的执行,(这样就导致了主线程执行栈中的同步代码没执行完,然后队列中的异步任务就不会执行) 同时暂停计时,点击确定后,恢复程序执行和计时