线性机制与事件机制

210318-20

1、进程与线程
  1. 进程(process):

    • 程序的一次执行,它占有一片独有的内存空间
    • 可以通过Windows任务管理器查看进程
  2. 线程(thread):

    • 是进程内的一个独立执行单元
    • 是程序执行的一个完整流程
    • 是CPU的最小的调度单元
  3. 图解

  4. 相关知识

    1. 应用程序必须运行在某个进程的某个线程上
    2. 一个进程中至少有一个运行的线程:主线程,进程启动后自动创建
    3. 一个进程中也可以同时运行多个线程,会说程序是多线程运行的
    4. 一个进程内的数据可以供其中的多个线程直接共享
    5. 多个进程之间的数据是不能直接共享的
    6. 线程池(thread pool):保存多个线程对象的容器,实现线程对象的反复利用
  5. 相关问题

    • 何为多进程与多线程?
      • 多进程运行:一个应用程序可以同时启动多个线程运行
      • 多线程:在一个进程内,同时有多个线程运行
    • 比较单线程与多线程?
      • 多线程
        • 优点:能有效提升CPU的利用率
        • 缺点:创建多线程开销、线程间切换开销(单核多线程,跳转运行),死锁与状态同步问题
      • 单线程
        • 优点:顺序编程简单易懂
        • 缺点:效率低
    • js是单线程还是多线程?
      • js是单线程运行的
      • 但使用h5中的web workers可以多线程运行
    • 浏览器运行时单线程还是多线程?
      • 都是多线程运行的
    • 浏览器运行是单进程还是多进程?
      • 有的是单进程:firefox,老版IE
      • 有的是多进程:chrome,新版IE
      • 如何查看浏览器是否是多进程运行的:Windows任务管理器
2、浏览器内核
  1. 支持浏览器运行的最核心的程序
  2. 不同浏览器可能不一样
    • chrome:blink
    • safari:webkit
    • firefox:Gecko
    • IE:trident
    • 360、搜狗等国内浏览器:trident(安全性高点)+webkit(双核双驱动)
  3. 内核由很多模块组成
    1. 主线程
      • js引擎模块:负责js程序的编译与运行
      • html,css文档解析模块:负责页面文本的解析
      • DOM/CSS模块:负责dom/css在内存中的相关处理
      • 布局和渲染模块:负责页面的布局和效果的绘制(内存中的对象)
    2. 分线程
      • 定时器模块:负责定时器的管理
      • DOM事件模块:负责事件的管理(异步)
      • 网络请求模块:负责ajax请求
3、定时器引发的思考
  1. 定时器并不能保持真正定时执行
  2. 一般会延迟一点(可以接受),也有可能延迟很长时间
  3. 定时器回调函数在主线程执行的,js是单线程的
  4. 定时器的实现是事件循环模型
document.getElementById('btn').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++){

    }
}
<button id="btn"></button>
4、js是单线程执行的
  1. 如何证明js执行是单线程
    • setTimeout()的回调函数是主线程执行的
    • 定时器回调函数只有在运行栈中的代码全部执行完后才有可能执行
  2. 为什么js要用单线程模式,而不是多线程模式?
    • javascript的单线程,与它的用途有关
    • 作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM(多个用户操作同一个对象是,只能是一个接一个操作,只有一个线程更新操作界面)
    • 这决定了他只能是单线程,否则会带来很复杂的同步问题
  3. 代码分类:
    • 初始化代码:包括绑定DOM时间监听,设置定时器,发送ajax请求代码
    • 回调代码:处理回调逻辑
  4. js引擎执行代码的基本流程(初始化代码-->回调代码)
    • 先执行初始化代码:包含一些特别的代码 回调函数(异步执行)
      • 设置定时器
      • 绑定事件监听
      • 发送ajax请求
    • 后面在某个时刻才会执行回调函数
setTimeout(function(){
    console.log('222222')
},2000)
setTimeout(function(){
    console.log('11111')
},1000)
setTimeout(function(){
    console.log('00000')
},0)
function fn(){
   console.log('fn()') 
}
fn()
console.log('alert()之前')
alert('-------') //暂停当前主线程的执行,同时暂停计时,点击确定后,恢复程序执行和计时
console.log('alert()之后')


5、浏览器的事件循环(轮询)模型

模型的运转流程

  • 执行初始化代码,将事件回调函数交给对应模块管理
  • 当事件发生时,管理模块会将回到函数及其数据添加到回调队列中
  • 只有当初始化代码执行完后(可能要一定时间),才会遍历读取回调队列中的回调函数执行

  1. 执行栈
    • execution stack
    • 所有的代码都是在此空间中执行的
  2. 浏览器内核
    • browser core
    • js引擎模块(在主线程处理)
    • 其他模块(在主/分线程处理)
  3. 同一个:callback queue
    • 任务队列:task queue
    • 消息队列:message queue
    • 事件队列:event queue
  4. 事件轮询
    • event loop
    • 从任务队列中循环取出回调函数放入执行栈中处理(一个接一个)
  5. 事件驱动模式
    • event-driven interaction model
  6. 请求响应模型
    • request-response model
6、H5 Web Workers(多线程)
  1. 介绍
    • h5规范提供了js多线程的实现(解决方案)取名:web workers
    • 可以将一些大计算量的代码交由web worker运行而不冻结用户界面
    • 但是子线程完全受主线程控制,且不得操作DOM(分线程中this不是window对象)。所有,这个新标准并没有改变JavaScript单线程的本质
  • 只有主线程更新界面
  1. 使用

    • 创建在分线程执行的js文件
    • 在主线程中的js中发消息并设置回调
    //web workers测试.html中
    var input = document.getElementById("number")
    document.getElementById('btn').onclick = function(){
        var number = input.value
        //创建一个worker对象并向它传递将在新线程中执行的脚本的URL
        var worker = new Worker('worker.js')
        //绑定接收消息的监听,接收worker传过来的数据函数
        worker.onmessage = function(event){
            console.log("主线程接收分线程返回的数据:"+event.data)
            alert(event.data)
        }
        //向分线程发送消息
        worker.postMessage(number)
        console.log('主线程向分线程发送数据:'+number)
    }
    
    /*创建在分线程执行的js文件worker.js*/
    function fibonacci(n){
        return n<=2 ? 1 : fibonacci(n-1) + fibonacci(n-2)//递归调用
    }
    var onmessage = function(event){//不能函数声明
        var number = event.data
        console.log('分线程接收到主线程发送的数据:'+number);
        var result = fibonacci(number)
        postMessage(result);
        console.log('分线程向主线程返回数据:'+result);
    }
    console.log(this) //不是window,不能使用window的方法alert
    //分线程中的全局对象不再是window,所以在分线程中不可能更新界面
    
    
  2. 图解

  3. 相关api

    • Worker:构造函数,加载分线程执行的js文件
    • Worker.prototype.onmessage:用于接收另一个线程的回调函数
    • Worker.prototype.postMessage:向另一个线程发送消息
  4. 不足

    • worker内代码不能操作DOM(更新UI)(全局对象不再是window)
    • 不能跨域加载js
    • 不是每个浏览器都支持这个新特性
posted @ 2021-07-14 14:53  STRIVE-PHY  阅读(58)  评论(0编辑  收藏  举报