线程机制与事件机制

Posted fsg6

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程机制与事件机制相关的知识,希望对你有一定的参考价值。

进程与线程

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4   <meta charset="UTF-8">
 5   <title>01_进程与线程</title>
 6 </head>
 7 <body>
 8 <!--
 9 1. 进程:程序的一次执行, 它占有一片独有的内存空间
10 2. 线程: CPU的基本调度单位, 是程序执行的一个完整流程
11 3. 进程与线程
12   * 一个进程中一般至少有一个运行的线程: 主线程
13   * 一个进程中也可以同时运行多个线程, 我们会说程序是多线程运行的
14   * 一个进程内的数据可以供其中的多个线程直接共享
15   * 多个进程之间的数据是不能直接共享的
16 4. 浏览器运行是单进程还是多进程?
17   * 有的是单进程
18     * firefox
19     * 老版IE
20   * 有的是多进程
21     * chrome
22     * 新版IE
23 5. 如何查看浏览器是否是多进程运行的呢?
24   * 任务管理器==>进程
25 6. 浏览器运行是单线程还是多线程?
26   * 都是多线程运行的
27 -->
28 </body>
29 </html>

 

浏览器内核

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4   <meta charset="UTF-8">
 5   <title>02_浏览器内核</title>
 6 </head>
 7 <body>
 8 <!--
 9 1. 什么是浏览器内核?
10   * 支持浏览器运行的最核心的程序
11 2. 不同的浏览器可能不太一样
12   * Chrome, Safari: webkit
13   * firefox: Gecko
14   * IE: Trident
15   * 360,搜狗等国内浏览器: Trident + webkit
16 3. 内核由很多模块组成
17   * html,css文档解析模块 : 负责页面文本的解析
18   * dom/css模块 : 负责dom/css在内存中的相关处理
19   * 布局和渲染模块 : 负责页面的布局和效果的绘制
20   * 布局和渲染模块 : 负责页面的布局和效果的绘制
21 
22   * 定时器模块 : 负责定时器的管理
23   * 网络请求模块 : 负责服务器请求(常规/Ajax)
24   * 事件响应模块 : 负责事件的管理
25 -->
26 </body>
27 </html>

 

定时器思考

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4   <meta charset="UTF-8">
 5   <title>03_定时器引发的思考</title>
 6 </head>
 7 <body>
 8 
 9 <button id="btn">启动定时器</button>
10 
11 <!--
12 1. 定时器真是定时执行的吗?
13   * 定时器并不能保证真正定时执行
14   * 一般会延迟一丁点(可以接受), 也有可能延迟很长时间(不能接受)
15 2. 定时器回调函数是在分线程执行的吗?
16   * 在主线程执行的, js是单线程的
17 3. 定时器是如何实现的?
18   * 事件循环模型(后面讲)
19 -->
20 <script type="text/javascript">
21 
22   document.getElementById(btn).onclick = function () {
23     var start = Date.now()
24     console.log(启动定时器前...)
25     setTimeout(function () {
26       console.log(定时器执行了, Date.now()-start)  //初始化代码(主线程)执行完后,才执行
27     }, 200)
28     console.log(启动定时器后...)
29 
30     // 做一个长时间的工作
31     for (var i = 0; i < 1000000000; i++) {
32 
33     }
34   }
35 </script>
36 </body>
37 </html>

 

JS是单线程的

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4   <meta charset="UTF-8">
 5   <title>04_JS是单线程的</title>
 6 </head>
 7 <body>
 8 <!--
 9 1. 如何证明js执行是单线程的?
10   * setTimeout()的回调函数是在主线程执行的,进入队列中,先入先出
11   * 定时器回调函数只有在运行栈中的代码全部执行完后才有可能执行
12 2. 为什么js要用单线程模式, 而不用多线程模式?
13   * JavaScript的单线程,与它的用途有关。
14   * 作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。
15   * 这决定了它只能是单线程,否则会带来很复杂的同步问题
16 
17 3. 代码的分类:
18   * 初始化代码
19   * 回调代码
20 4. js引擎执行代码的基本流程
21   * 先执行初始化代码: 包含一些特别的代码   回调函数(异步执行)
22     * 设置定时器
23     * 绑定事件监听
24     * 发送ajax请求
25   * 后面在某个时刻才会执行回调代码
26 -->
27 <script type="text/javascript">
28   setTimeout(function () {   //第二个延时计时器一秒后,再过一秒就开始执行了
29     console.log(timeout 2222)
30     alert(22222222)
31   }, 2000)
32   setTimeout(function () {
33     console.log(timeout 1111)
34     alert(1111111)
35   }, 1000)
36   setTimeout(function () {
37     console.log(timeout() 00000)
38   }, 0)
39   function fn() {
40     console.log(fn())
41   }
42   fn()
43 
44   console.log(alert()之前)
45   alert(------) //暂停当前主线程的执行, 同时暂停计时, 点击确定后, 恢复程序执行和计时
46   console.log(alert()之后)
47 
48   //执行顺序;alert()之前,------, alert()之后, 0秒延时,1秒延时,2秒延时
49 //如果初始化代码执行的时间大于延时定时器的时间,执行完了初始化代码,就执行延时定时器的回调函数执行了
50 //如果初始化的代码执行的时间小于延时定时器的时间,那个执行初始化后,还要等待延时时间完了后执行回调函数
51 
52 </script>
53 </body>
54 </html>

 

事件循环模型

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4   <meta charset="UTF-8">
 5   <title>05_事件循环模型</title>
 6 </head>
 7 <body>
 8 <button id="btn">测试</button>
 9 <!--
10 1. 所有代码分类
11   * 初始化执行代码(同步代码): 包含绑定dom事件监听, 设置定时器, 发送ajax请求的代码
12   * 回调执行代码(异步代码): 处理回调逻辑
13 2. js引擎执行代码的基本流程:
14   * 初始化代码===>回调代码
15 3. 模型的2个重要组成部分:
16   * 事件(定时器/DOM事件/Ajax)管理模块
17   * 回调队列
18 4. 模型的运转流程
19   * 执行初始化代码, 将事件回调函数交给对应模块管理
20   * 当事件发生时, 管理模块会将回调函数及其数据添加到回调列队中
21   * 只有当初始化代码执行完后(可能要一定时间), 才会遍历读取回调队列中的回调函数执行
22 -->
23 <script type="text/javascript">
24   function fn1() {
25     console.log(fn1())
26   }
27   fn1()
28   document.getElementById(btn).onclick = function () {
29     console.log(点击了btn)
30   }
31   setTimeout(function () {
32     console.log(定时器执行了)
33   }, 2000)
34   function fn2() {
35     console.log(fn2())
36   }
37   fn2()
38 </script>
39 </body>
40 </html>

 

技术图片

 

 

菲波列切计算

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4   <meta charset="UTF-8">
 5   <title>06_Web Workers_测试</title>
 6 </head>
 7 <body>
 8 <!--
 9 1. H5规范提供了js分线程的实现, 取名为: Web Workers
10 2. 相关API
11   * Worker: 构造函数, 加载分线程执行的js文件
12   * Worker.prototype.onmessage: 用于接收另一个线程的回调函数
13   * Worker.prototype.postMessage: 向另一个线程发送消息
14 3. 不足
15   * worker内代码不能操作DOM(更新UI)
16   * 不能跨域加载JS
17   * 不是每个浏览器都支持这个新特性
18 -->
19 
20 <input type="text" placeholder="数值" id="number">
21 <button id="btn">计算</button>
22 <script type="text/javascript">
23   // 1 1 2 3 5 8    f(n) = f(n-1) + f(n-2)
24   function fibonacci(n) {
25     return n<=2 ? 1 : fibonacci(n-1) + fibonacci(n-2)  //递归调用,计算的次数太多,耗时严重,dom对象操作卡死
26   }
27   // console.log(fibonacci(7))
28   var input = document.getElementById(number)
29   document.getElementById(btn).onclick = function () {
30     var number = input.value   //需要将该数据交给分线程去处理计算,然后将结果返回给主线程
31     var result = fibonacci(number)
32     alert(result)
33   }
34 
35 </script>
36 </body>
37 </html>

 

H5规范提供了js分线程的实现,  Web Workers
 
主线程
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4   <meta charset="UTF-8">
 5   <title>06_Web Workers_测试</title>
 6 </head>
 7 <body>
 8 <!--
 9 1. H5规范提供了js分线程的实现, 取名为: Web Workers
10 2. 相关API
11   * Worker: 构造函数, 加载分线程执行的js文件
12   * Worker.prototype.onmessage: 用于接收另一个线程的回调函数
13   * Worker.prototype.postMessage: 向另一个线程发送消息
14 3. 不足
15   * worker内代码不能操作DOM(更新UI)
16   * 不能跨域加载JS
17   * 不是每个浏览器都支持这个新特性
18 -->
19 
20 <input type="text" placeholder="数值" id="number">
21 <button id="btn">计算</button>
22 <script type="text/javascript">
23   var input = document.getElementById(number)
24   document.getElementById(btn).onclick = function () {
25     var number = input.value   //需要将该数据交给分线程去处理计算,然后将结果返回给主线程
26 
27     //创建一个Worker对象
28     var worker = new Worker(./worker.js)
29     // 绑定接收消息的监听
30     worker.onmessage = function (event) {  //回调函数,异步执行,将主线程的代码执行完后,才会执行
31       console.log(主线程接收分线程返回的数据: +event.data)
32       alert(event.data)
33     }
34 
35     // 向分线程发送消息
36     worker.postMessage(number)
37     console.log(主线程向分线程发送数据: +number)
38   }
39   // console.log(this) // window
40 
41 </script>
42 </body>
43 </html>

 

分线程

 1 function fibonacci(n) {
 2   return n<=2 ? 1 : fibonacci(n-1) + fibonacci(n-2)  //递归调用
 3 };
 4 
 5 // console.log(this)
 6 this.onmessage = function (event) {
 7   var number = event.data
 8   console.log(‘分线程接收到主线程发送的数据: ‘+number)
 9   //计算
10   var result = fibonacci(number)
11   postMessage(result)
12   console.log(‘分线程向主线程返回数据: ‘+result)
13   // alert(result)  alert是window的方法, 在分线程不能调用
14   // 分线程中的全局对象不再是window, 所以在分线程中不可能更新界面
15 }

 

技术图片

 

 

以上是关于线程机制与事件机制的主要内容,如果未能解决你的问题,请参考以下文章

线程机制与事件机制

JavaScript线程机制与事件机制

线程机制与事件机制:进程与线程 浏览器内核 定时器引发的思考 JS是单线程执行的 浏览器的事件循环(轮询)模型

详解 JavaScript 中的 EventtLoop(事件循环)机制

JavaScript中事件处理机制

除了信号触发线程与接收者线程相同的情况能直接调用到slot,其它情况都依赖事件机制(解决上面代码收不到信号的问题其实很简单,在线程的run();函数中添加一个事件循环就可以了,即加入一句exec();