线程机制与事件机制

271 阅读6分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情

线程机制与事件机制

进程与线程

进程概念:
进程是程序的一次执行,它占有一片独有的内存空间
可以通过window任务管理器查看进程,并且各个应用程序之间的内存是相互独立的,不会轻易访问到另外一个应用程序的内存

线程概念:
线程是进程内的一个独立执行单元
是程序执行的一个完整流程
是CPU的最小的调度单元

两者的关系:
一个进程中一般至少有一个运行的线程:主线程
一个进程中也可以同时运行多个线程,我们会说程序是多线程运行的
一个进程内的数据可以供其中的多个线程直接共享
多个进程之间的数据是不能直接共享的

浏览器运行是单进程还是多进程?
答:有些是单进程,有些是多进程。比如老板IE和火狐就是单进程的,chrome和新版IE是多进程的。

图解

image.png

如上图,我们的应用程序存储在硬盘上面,接着我们启动程序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之后--');

以下是上面代码的输出顺序:

image.png

image.png

image.png

image.png

image.png

alert的特点就是暂停当前主线程代码的执行,(这样就导致了主线程执行栈中的同步代码没执行完,然后队列中的异步任务就不会执行) 同时暂停计时,点击确定后,恢复程序执行和计时