资讯专栏INFORMATION COLUMN

【11】JavaScript 线程机制与事件机制

fobnn / 2435人阅读

摘要:线程机制与事件机制一进程与线程进程程序的一次执行,它占有一片独有的内存空间。事件响应模块负责事件的管理。当事件发生时管理模块会将回调函数及其数据添加到回调列队中。但是子线程完全受主线程控制,且不得操作。向另一个线程发送消息。

JavaScript线程机制与事件机制 一、进程与线程 进程(process

程序的一次执行,它占有一片独有的内存空间。

可以通过windows任务管理器查看进程。

线程(thread

是进程内的一个独立执行单元。

是程序执行的一个完整流程。

CPU的最小调度单元。

进程与线程图解

相关知识

应用程序必须运行在某个进程的某个线程上。

一个进程中至少有一个运行的线程:主线程,进程启动后自动创建。

一个进程中也可以同时运行多个线程,我们会说程序是多线程运行的。

一个进程内的数据可以供其中的多个线程中直接共享。

多个进程之间的数据是不能直接共享的。

线程池(thread pool):保存多个线程对象的容器,实现线程对象的反复利用。

相关问题

(1)何为多进程与多线程?

多进程运行:一个应用程序可以同时启动多个实例运行。

多线程:在一个进程内,同时有多个线程运行。

(2)比较单线程与多线程?

多线程

优点:能有效提升CPU的利用率。

缺点:

创建多线程开销。

线程间切换开销。

死锁与状态同步问题。

单线程

优点:顺序编程简单易懂。

缺点:效率低。

(3)JS是单线程还是多线程?

JS是单线程运行的。

但是使用H5中的 Web Workers可以多线程运行。

(4)浏览器运行是单线程还是多线程?

浏览器都是多线程运行的。

(5)浏览器运行是单进程还是多进程?

有的是单进程:

老版Firefox

老版IE

有的是多进程:

Chrome

新版Firefox

新版IE

如何查看浏览器是否是多进程运行的呢?

任务管理器==>进程

二、浏览器内核

(1)浏览器内核是支撑浏览器运行的最核心的程序。

(2)不同的浏览器内核不一样:

ChromeSafariwebkit

FirefoxGecko

IETrident

360,搜狗等国内浏览器:Trident+webkit

(3)内核由很多模块组成:

主线程

js引擎模块:负责js程序的编译与运行。

html,css文档解析模块:负责页面文本的解析。

DOM/CSS模块:负责DOM/CSS在内存中的相关处理。

布局和渲染模块:负责页面的布局和效果的绘制(内存中的对象)

分线程

定时器模块:负责定时器的管理。

DOM事件响应模块:负责事件的管理。

网络请求模块:负责服务器请求(常规/ajax)。

三、定时器引发的思考

(1)定时器真是定时执行的吗?

定时器并不能保证真正定时执行。

一般会延迟一丁点(可以接受), 也有可能延迟很长时间(不能接受)。



document.getElementById("btn").onclick = function () {
  var start = Date.now()
  console.log("启动定时器前...")
  setTimeout(function () {
    console.log("定时器执行了", Date.now()-start)
  }, 200)
  console.log("启动定时器后...")
}

给上面回调函数加一个长时间的任务:

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++) {}
}

结果:

同步任务执行完之后才会执行异步任务。

(2)定时器回调函数是在分线程执行的吗?

在主线程执行的, js是单线程的。

(3)定时器是如何实现的?

事件循环模型(后面讲)。

四、JS是单线程执行的

(1)如何证明js执行是单线程的?

setTimeout()的回调函数是在主线程执行的。

定时器回调函数只有在运行栈中的代码全部执行完后才有可能执行。

(2)为什么js要用单线程模式, 而不用多线程模式?

JavaScript的单线程,与它的用途有关。

作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM

这决定了它只能是单线程,否则会带来很复杂的同步问题

(3)代码的分类:

初始化代码

回调代码

(4)js引擎执行代码的基本流程

先执行初始化代码: 包含一些特别的代码 ,回调函数(异步执行)

设置定时器

绑定监听

发送ajax请求

后面在某个时刻才会执行回调代码。

五、浏览器的事件循环(轮询)模型 浏览器的事件循环模型原理图

相关重要概念

(1)执行栈

execution stack

所有的代码都是在此空间中执行的。

(2)浏览器内核

browser core

js引擎模块(在主线程处理)

其它模块(在主/分线程处理)

(3)任务队列(callback queue)

task queue

(4)消息队列(callback queue)

message queue

(5)事件队列(callback queue)

event queue

(6)事件轮询

event loop

从任务队列中循环取出回调函数放入执行栈中处理(一个接一个)。

(7)事件驱动模型

event-driven interaction model

(8)请求响应模型

request-response model

执行流程

(1)所有代码分类:

初始化执行代码:包含绑定dom事件监听, 设置定时器, 发送ajax请求的代码。

回调执行代码:处理回调逻辑。

(2)js引擎执行代码的基本流程:

初始化代码===>回调代码

(3)模型的2个重要组成部分:

事件管理模块

回调队列

(4)模型的运转流程

​ (a)执行初始化代码, 将事件回调函数交给对应模块管理。

​ (b)当事件发生时, 管理模块会将回调函数及其数据添加到回调列队中。

​ (c)只有当初始化代码执行完后(可能要一定时间), 才会遍历读取回调队列中的回调函数执行。

六、H5 Web Workers(多线程) 介绍

Web WorkersHTML5 提供的一个Javascript多线程解决方案。

我们可以将一些大计算量的代码交由Web Worker运行而不冻结用户界面。

但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质

使用

相关API

Worker: 构造函数, 加载分线程执行的js文件。

Worker.prototype.onmessage: 用于接收另一个线程的回调函数。

Worker.prototype.postMessage: 向另一个线程发送消息。

创建在分线程执行的JS文件

var onmessage = function (event){ //不能用函数声明
    console.log("onMessage()22");
    var upper = event.data.toUpperCase();//通过event.data获得发送来的数据
    postMessage( upper );//将获取到的数据发送回主线程
}

在主线程中的JS中发消息并设置回调

//创建一个Worker对象并向它传递将在新线程中执行的脚本的URL
var worker = new Worker("worker.js");  
//接收worker传过来的数据函数
worker.onmessage = function (event) {     
    console.log(event.data);             
};
//向worker发送数据
worker.postMessage("hello world");    
图解

应用练习
编程实现斐波那契数列(Fibonacci sequence)的计算

F(0)=0,F(1)=1,..... F(n)=F(n-1)+F(n-2)

直接在主线程:

var fibonacci =function(n) {
    return n <2 ? n : fibonacci(n -1) + fibonacci(n -2);
};
console.log(fibonacci(48));

使用Web Workers在分线程:

主线程:

var worker = new Worker("worker2.js");
worker.addEventListener("message", function (event) {
    var timer2 = new Date().getTime();
    console.log("结果:" + event.data, "时间:" + timer2, "用时:" + ( timer2 - timer ));
}, false);
var timer = new Date().getTime();
console.log("开始计算: ", "时间:" + timer);
setTimeout(function () {
    console.log("定时器函数在计算数列时执行了", "时间:" + new Date().getTime());
}, 1000);
worker.postMessage(40);
console.log("我在计算数列的时候执行了", "时间:" + new Date().getTime());

分线程:

var fibonacci =function(n) {
    return n <2 ? n : fibonacci(n -1) + fibonacci(n -2);
};
var onmessage = function(event) {
    var n = parseInt(event.data, 10);
    postMessage(fibonacci(n));
};

不足

慢。

不能跨域加载JS

worker内代码不能访问DOM(更新UI)。

不是每个浏览器都支持这个新特性。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105093.html

相关文章

  • JSNode.js中的事件循环

    摘要:的单线程,与它的用途有关。特点的显著特点异步机制事件驱动。队列的读取轮询线程,事件的消费者,的主角。它将不同的任务分配给不同的线程,形成一个事件循环,以异步的方式将任务的执行结果返回给引擎。 这两天跟同事同事讨论遇到的一个问题,js中的event loop,引出了chrome与node中运行具有setTimeout和Promise的程序时候执行结果不一样的问题,从而引出了Nodejs的...

    abson 评论0 收藏0
  • 这一次,彻底弄懂 JavaScript 执行机制

    摘要:事件完成,回调函数进入。主线程从读取回调函数并执行。终于执行完了,终于从进入了主线程执行。遇到,立即执行。宏任务微任务第三轮事件循环宏任务执行结束,执行两个微任务和。事件循环事件循环是实现异步的一种方法,也是的执行机制。 本文的目的就是要保证你彻底弄懂javascript的执行机制,如果读完本文还不懂,可以揍我。不论你是javascript新手还是老鸟,不论是面试求职,还是日常开发工作...

    dreambei 评论0 收藏0
  • JavaScript执行机制

    摘要:事件循环事件循环是实现异步的一种方法,也是的执行机制。最后的最后是一门单线程语言是的执行机制部分内容转自 1.单线程 javascript是一门单线程语言 2.javascript事件循环 同步任务 异步任务 showImg(https://segmentfault.com/img/bVbufUd?w=1268&h=1062);除了广义的同步任务和异步任务,我们对任务有更精细的定义...

    ralap 评论0 收藏0
  • 彻底弄懂 JavaScript 执行机制

    摘要:关于这部分有严格的文字定义,但本文的目的是用最小的学习成本彻底弄懂执行机制,所以同步和异步任务分别进入不同的执行场所,同步的进入主线程,异步的进入并注册函数。宏任务微任务第三轮事件循环宏任务执行结束,执行两个微任务和。 不论你是javascript新手还是老鸟,不论是面试求职,还是日常开发工作,我们经常会遇到这样的情况:给定的几行代码,我们需要知道其输出内容和顺序。 因为javascr...

    gyl_coder 评论0 收藏0
  • 深入前端-彻底搞懂JS的运行机制

    摘要:浏览器是多进程的详情看我上篇总结浏览器执行机制的文章深入前端彻底搞懂浏览器运行机制浏览器每打开一个标签页,就相当于创建了一个独立的浏览器进程。执行异步操作事件完成,回调函数进入。主线程从读取回调函数并执行。 最近看了很多关于JS运行机制的文章,每篇都获益匪浅,但各有不同,所以在这里对这几篇文章里说的很精辟的地方做一个总结,参考文章链接见最后。本文博客地址 了解进程和线程 进程是应用...

    luckyw 评论0 收藏0

发表评论

0条评论

fobnn

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<