web worker创建多个 JavaScript 线程 (使用GTP写的文章)

news2024/11/17 7:56:43

前言

最近在优化公司的一个项目,使用的就是web worker去优化,做了那些优化,一个是状态的优化,(通信的状态实时更新,以前的做法是做个定时任务实时获取它的状态,然后让它在页面渲染,这样就会造成了,一个是定时任务,实时获取,一个是一直在不断的渲染,虽然肉眼看不出什么,但是这样会造成一个主进程的负担非常大,然后我就引用了web worker开一个进程给它,定时去获取,然后在做判断是否与前面的状态是否一致,一致不传入主进程,不一致传入,然后这样就可以页面的明显的比较丝滑了)还有一个就是做一个计算,涉及到了比较复杂的数据,然后也是在web worker计算好了在传入主线程。最后用来做文件的下载,因为我们的文件涉及到了视频的下载,有些视频几个G的下载,那就是用了这个来处理。这篇文章呢,本来打算自己写的,然后做总结,然后自己比较懒,发现GPT写的比我还全面。当然我也参考了其它文章来看是否写的正常,对比MDN.

在这里插入图片描述

Web Worker 是一项 HTML5 标准中的特性,可以在 Web 页面中创建多个 JavaScript 线程,从而实现多线程并行执行代码的效果。它是为了解决 JavaScript 在单线程下的并发执行问题而出现的。使用 Web Worker 可以使 UI 界面保持流畅和响应性,并有效地利用计算机的硬件资源,提高 Web 应用程序的性能和响应速度。

Web Worker 主要有两种类型:Dedicated Worker 和 Shared Worker。Dedicated Worker 是指只与一个页面相关联的 Worker,而 Shared Worker 则是可以被多个页面共享的 Worker。Worker 可以操作独立的数据副本,这些数据副本在线程之间通信时不会互相干扰,并可以使用 postMessage() 方法进行相互通信。

下面详细介绍 Web Worker 的相关知识点:

1.Web Worker 基本用法

Web Worker 最重要的作用是将一部分代码运行在另一个线程中,用以减轻主线程负荷,以达到提高网页性能的目的。

使用 Worker API 来创建一个后台工作者线程,语法如下:

// 创建一个 Worker 线程
var myWorker = new Worker('worker.js');

其中,worker.js 为后台线程所要执行的 JavaScript 文件。

2.Dedicated Worker 和 Shared Worker

Web Worker 分为两种类型:Dedicated Worker 和 Shared Worker。Dedicated Worker 是指只与一个页面相关联的 Worker,而 Shared Worker 则是可以被多个页面共享的 Worker。

Dedicated Worker 的创建方式比较简单,而 Shared Worker 的使用方法则比较复杂。例如,当多个页面同时使用同一个 Shared Worker 时,它们在访问该 Worker 时必须保证具有相同的域名和端口号。

3.postMessage() 和 onmessage 事件

Dedicated Worker 和主线程之间可以通过 postMessage() 方法来传递消息,在 Dedicated Worker 中可以使用 self 属性代替 this,其中 self.postMessage() 用于向主线程发送消息。

主线程接收后台 Worker 发送过来的信息,可以通过 onmessage 事件进行处理,代码如下:

// 主线程代码
// 创建 Worker
var myWorker = new Worker('worker.js');
// 接收来自 Worker 的消息并进行处理
myWorker.onmessage = function(event) {
  console.log('Received message from worker:', event.data);
};

4.线程与锁

由于 JavaScript 实现不支持锁,因此 Web Worker 的实现也没有锁概念。但可以借助 MessageChannel API 来模拟锁,即将信道分成互斥的“写入键”和“读取键”,从而控制对数据结构的访问。

5.限制和局限性

Web Worker 在实际使用时也存在一些限制和局限性,例如:

  • Web Worker 脚本不能访问 DOM。
  • Web Worker 不能从主线程中调用函数或方法。
  • 所有的 worker 线程必须遵守同源策略。

6.发送和接收二进制数据

Web Worker API 允许在主线程和后台线程之间交换二进制数据,以及共享 ArrayBuffer 和 MessagePort 对象。可以使用 postMessage() 方法发送 ArrayBuffers、TypedArrays 和 DataViews。 示例代码如下:

// 计算行列式
function determinant(matrix) {
  var length = matrix.length;
  if (length === 2) {
    return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
  } else {
    var result = 0;
    var cofactor = 1;
    for (var i = 0; i < length; i++) {
      var minor = [];
      for (var j = 1; j < length; j++) {
        minor.push(matrix[j].slice(0, i).concat(matrix[j].slice(i + 1)));
      }
      result += cofactor * matrix[0][i] * determinant(minor);
      cofactor = -cofactor;
    }
    return result;
  }
}
 
// 主线程
var myWorker = new Worker('worker.js');
myWorker.onmessage = function(event) {
  console.log('Received worker message:', event.data);
};
// 创建 ArrayBufer,这里是一个 4x4 的矩阵
var buffer = new ArrayBuffer(64);
var view = new Int32Array(buffer);
for (var i = 0; i < 16; i++) {
  view[i] = i;
}
// 向 worker 发送 ArrayBuffer
myWorker.postMessage(buffer, [buffer]);

错误处理
在 Web Worker 中,当代码执行出现错误时,会抛出一个相应的异常。Worker 可以通过将错误对象传递给主线程来报告错误。示例代码如下:

// 后台 Worker 代码示例,计算阶乘
self.onmessage = function(event) {
  var n = event.data;
  if (n < 0) {
    self.postMessage('Error: argument must be non-negative');
  } else {
    var result = 1;
    for (var i = 2; i <= n; i++) {
      result *= i;
    }
    self.postMessage(result);
  }
};

8.性能优化

使用 Web Worker 进行性能优化时,可以考虑以下几点:

  • 确保创建 Worker 的开销不要过大。
  • 尽可能重用 Worker 实例,而不是在每次需要多线程执行时都新建一个 Worker 对象。
  • 调整 Worker 线程数量和运行策略,常见的有按需启动、固定数量和循环调度等。

9. 消息传递

Web Worker 之间通过消息传递进行通信。可以使用 postMessage() 和 onmessage 属性在主线程和 Worker 之间发送和接收消息。示例代码如下:

// 主线程
var myWorker = new Worker('worker.js');
myWorker.onmessage = function(event) {
  console.log('Received worker message:', event.data);
};
myWorker.postMessage(42);
 
// 后台 Worker 代码示例
self.onmessage = function(event) {
  console.log('Received message from main thread:', event.data);
  self.postMessage('Hello, main thread!');
};

10.终止\关闭 Worker

可以使用 terminate() 方法终止 Worker 线程。示例代码如下:

// 主线程
var myWorker = new Worker('worker.js');
myWorker.postMessage(42);
// 等待 2 秒后终止 Worker 线程
setTimeout(function() {
  myWorker.terminate();
  console.log('Worker terminated.');
}, 2000);
 
// 后台 Worker 代码示例
self.onmessage = function(event) {
  console.log('Received message from main thread:', event.data);
};

11. Web Worker API

除了上面提到的方法和属性,Web Worker 还提供了一些其他的 API,包括:

  • importScripts():在 Worker 中加载脚本。
  • close():关闭 Worker 线程。
  • XMLHttpRequest:在 Worker 中发起网络请求。
  • WorkerGlobalScope:Worker 全局作用域,不同于浏览器中的全局作用域。
  • navigator、location、console 等对象:这些对象在 Worker 中与主线程中的对象略有差异,最突出的是它们不支持 DOM 操作。

12 .Worker 线程安全

Worker 线程执行的代码必须是线程安全的,因为它们在多个线程中同时运行。具体来说,Worker 线程不能访问主线程的 DOM、BOM 或 JavaScript 对象,而是操作自己的局部变量和引入的脚本库。由于共享内存的特性,如果多个 Worker 同时读写同一个共享变量,可能会导致数据竞争和不可预期的结果。

13.使用 SharedArrayBuffer 共享内存

SharedArrayBuffer 是 HTML5 的新增特性,可以在多个 Worker 之间共享内存。与普通数组不同,SharedArrayBuffer 的操作是原子性的,能够保证多个线程同时读写 SharedArrayBuffer 不会出现竞争和冲突。

使用 SharedArrayBuffer 需要注意以下问题:

  • SharedArrayBuffer 必须显式地分配指定长度的空间。
  • 可以使用 TypedArray(如 Int8Array、Float32Array 等)对 SharedArrayBuffer 进行操作。
  • 需要注意内存一致性问题,即各个线程操作相同的内存区域时需要协调好读写的先后顺序和同步机制,避免读取到不一致的数据。

14. Web Worker 应用实例

Web Worker 可以用于许多场景,这里举几个实际应用的例子:

  • 图像处理:对于大型高分辨率图像,可以使用 Worker 将其切分为多个小部分,并利用多核 CPU 并行处理各自分片,以提高计算效率。
  • 负载均衡:可以使用 Worker 平均分配服务器请求任务,避免某一线程负载过高。
  • 实时通信:可以使用 Worker 处理客户端与服务端的双向通信,以协调客户端发送和接收消息的操作。

15.Web Worker 的限制

Web Worker 主要有以下几个限制:

  • 无法访问 DOM:Worker 线程运行在与主线程不同的上下文环境中,无法访问主线程的 DOM 对象。
  • 不能使用 alert()、prompt() 和 confirm() 方法:这些方法是阻塞主线程的,但是在 Worker 线程调用会导致浏览器崩溃。
    无法访问 window 和 document 对象:因为 Worker 线程没有 window 和 document 对象,所以它们无法访问这些对象。
  • 无法使用某些 JavaScript API:比如不能使用 localStorage 和 sessionStorage,因为它们都依赖于 window 对象。
  • 必须遵守同源策略:Worker 线程必须从与其本身代码文件相同的域名下加载其他脚本文件。

16.Web Worker 的兼容性问题

Web Worker 是 HTML5 中新增的特性,需要浏览器支持。目前绝大多数主流浏览器都支持 Web Worker,但是还有一些老版本的浏览器可能不支持。

为了解决兼容性问题,可以使用 Modernizr 库,检测当前浏览器是否支持 Web Worker,并提供相应的替代方案。

17.Web Worker 的调试技巧

由于 Worker 线程不能使用 alert()、console.log() 和调试工具,因此在调试 Web Worker 时可能比较困难。下面是一些调试技巧:

  • 在主线程中使用 console.log() 对消息进行调试:可以在后台 Worker 代码中发送和接收消息,在主线程中通过 console.log() 输出消息内容进行调试。
  • 使用 postMessage() 将错误信息传递回主线程:可以在 Worker 端捕获错误,并通过 postMessage() 方法将错误信息发送给主线程,同时在主线程中输出错误信息。
  • 利用浏览器开发工具:可以在 Chrome 和 Firefox 浏览器的开发者工具中查看 Worker 运行情况,例如 CPU 占用率、内存占用率等。

18.其它

Web Worker 还可以用于许多其他情况,例如:

  • 大规模数据处理:对于需要进行复杂数学计算或其他计算密集型操作的大规模数据集,可以使用多个 Worker 在后台并行处理,加快计算速度和提高性能。
  • 实现离线缓存:通过在 Worker 中缓存 Web 应用所需的静态资源,即使用户处于断网状态,也可以优化 Web 应用的体验,减少页面加载时间。
  • 计时器和定时器操作:利用两个 Worker 计时器之间的双向消息传递,可以轻松实现精确的定时器操作,而不会受到主线程的占用和干扰。

总之,Web Worker 是一个非常强大且有用的工具,可以大幅提高 JavaScript 程序的性能和可维护性。但是一定要注意避免共享内存等问题,保证程序的正确性和安全性。

对比文章:(Exploring The Potential Of Web Workers For Multithreading On The Web)[https://www.smashingmagazine.com/2023/04/potential-web-workers-multithreading-web]
当然国内也有人去进行了一个翻译:译文
web worker使用:这篇第二种方式是有点问题的,不支持es6以上的语法,所以还是推荐使用worker-load
这篇:融会贯通
github也有人进行了一个简单的封装可以看看他:gitHub web worker

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/634491.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】 -- TCP协议 (一)

TCP协议 Tcp协议可靠性冯诺依曼体系结构 TCP的协议格式序号与确认序号窗口大小六个标志位 确认应答机制 &#xff08;ACK&#xff09;超时重传机制连接管理机制 Tcp协议 TCP全称为 “传输控制协议”&#xff08;Transmission Control Protocol&#xff09; TCP协议被广泛应用…

[linux_C语言_udp的多种实现方法及网络调试中遇到的问题]

linux_C语言_udp的多种实现方法 最基本的方式(不用组播不用sigio信号不使能广播属性)接收端发送端 使用SIGIO信号的方式(使用sigio信号使用广播使能属性)服务端客户端 使用组播模式服务端客户端 tcp和udp的使用区别调试中遇到的问题所有源码下载点这~~ 最基本的方式(不用组播不…

Unix/Linux编程:UDS 流(Stream)

〇、前言 socket 是一种 IPC &#xff08;Inter-Process Communication&#xff0c;进程间通信&#xff09;方法&#xff0c;它允许位于同一主机&#xff08;计算机&#xff09;或使用网络连接起来的不同主机上的应用程序之间交换数据。通过使用Socket&#xff0c;开发人员可以…

【C++】——栈和队列(stack、queue)及优先队列(priority_queue)的介绍和模拟实现

文章目录 1. 前言2. 容器适配器2.1 容器适配器的介绍2.2 STL标准库中stack和queue的底层结构2.3 deque的简单介绍2.4 deque的缺陷2.5 为什么选择deque作为stack和queue的底层默认容器 3. stack3.1 stack的介绍3.2 stack的使用3.3 stack模拟实现 4. queue4.1 queue的介绍4.2 que…

数据分布——长尾分布的处理

前言 长尾分布在分类任务中会提到这个名,这是因为长尾分布这个现象问题会导致在训练过程中会出现出错率高的问题&#xff0c;影响了实验结果。 这里要说的是&#xff0c;长尾分布是一种现象&#xff0c;有的地方说是一种理论或定律&#xff0c;我感觉这样说不太确切&#xff0…

取石子游戏——算法与编程

取石子游戏 目录 问题描述输入输出格式输入格式&#xff1a;输出格式&#xff1a; 输入输出样例输入样例#1&#xff1a;输出样例#1&#xff1a;提示信息 算法尼姆博奕 代码 问题描述 A l i c e Alice Alice和 B o b Bob Bob在玩取石子游戏&#xff0c;摆在他们面前的有 n n n堆…

GIS入门进阶之012

一、引言 空间数据可视化是有效传输与表达地理信息&#xff0c;挖掘空间数据之间的内在联系&#xff0c;揭示地理现象内在规律的重要手段。它通过运用地图学、计算机图形学和图像处理技术&#xff0c;将地学信息的输入、处理、查询、分析与预测的结果采用符号、图形、图像并结合…

OpenGL 材质实现

1.简介 在现实世界里&#xff0c;每个物体会对光产生不同的反应。比如&#xff0c;钢制物体看起来通常会比陶土花瓶更闪闪发光&#xff0c;一个木头箱子也不会与一个钢制箱子反射同样程度的光。有些物体反射光的时候不会有太多的散射&#xff0c;因而产生较小的高光点&#xf…

35岁被淘汰?软件测试工程师职业生涯规划,从技术到管理...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 入门阶段&#xf…

Parallel Desktop中按照的centos在切换root用户时,密码正确,但一直切换不成功,显示su: Authentication failure

目录 一、出现问题二、分析问题三、解决问题四、参考资料 一、出现问题 我的密码明明是输入正确的&#xff0c;但又一直给我报下面的错误 二、分析问题 我怀疑是我密码记错了&#xff0c;所以我点击Log Out&#xff0c;重新去输入了一下密码&#xff0c;发现是正确的我确认…

[学习笔记] [机器学习] 9. 朴素贝叶斯(概率基础、联合概率、条件概率、贝叶斯公式、情感分析)

视频链接数据集下载地址&#xff1a;无需下载 学习目标&#xff1a; 4. 说明条件概率与联合概率 5. 说明贝叶斯公式、以及特征独立的关系 6. 记忆贝叶斯公式 7. 知道拉普拉斯平滑系数 8. 应用贝叶斯公式实现概率的计算 9. 会使用朴素贝叶斯对商品评论进行情感分析 1. 朴素贝叶…

对象进阶-继承、原型-原型链

工厂方法创建对象 我们之前已经学习了如何创建一个对象&#xff0c;那我们要是想要创建多个对象又该怎么办&#xff1f;聪明的同学可能会说&#xff0c;直接在写几个对象不就好了吗&#xff1f;比如下边的代码&#xff1a; var person1 {name: "孙悟空",age: 18,s…

APP自动化测试,Appium+PO模式+Pytest框架实战—项目案例

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 PO模式&#xff1…

如何解决GEE导出影像的Nodata值在ArcGIS中无法正常显示?

目录 01 ArcGIS对于GEE掩膜影像的Nodata值的说明 02 处理方法 2.1 方法1-GEE修改掩膜值 Arguments: Returns: Image 2.2 方法2-ArcGIS重新赋值Nodata&#xff08;推荐&#xff09; 01 ArcGIS对于GEE掩膜影像的Nodata值的说明 当在GEE中进行掩膜后&#xff0c;将影像在Ar…

打造极简风格动效 —— 5 分钟轻松实现惊艳、震撼人心的视觉效果

前期回顾 是不是在为 API 烦恼 &#xff1f;好用免费的api接口大全呼之欲出_免流接口api_彩色之外的博客-CSDN博客APi、常用框架、UI、文档—— 整理合并https://blog.csdn.net/m0_57904695/article/details/130459417?spm1001.2014.3001.5501 &#x1f44d; 本文专栏&…

20道嵌入式经典面试题(附答案)

1.嵌入式系统中经常要用到无限循环&#xff0c;如何用C编写死循环 答&#xff1a;while(1){} 或者 for(;;) 2.程序的局部变量存在于哪里&#xff0c;全局变量存在于哪里&#xff0c;动态申请数据存在于哪里。 答&#xff1a;程序的局部变量存在于栈区&#xff1b;全局变量存在…

【Linux】浅谈文件原理与操作

目录 问题引入 浅谈文件原理 文件操作 文件的打开与关闭 open close write与read 再谈C库文件操作 问题引入 &#x1f338;以前我们学过C语言的文件操作&#xff0c;而不同语言的文件操作都是不一样的&#xff0c;我们该如何理解这一现象&#xff0c;能不能用一种统一…

有关 string 类的练习(下)

目录 一、反转字符串 II 二、反转字符串中的单词 III 三、找出字符串中第一个只出现一次的字符 四、字符串相乘 五、把字符串转换成整数 一、反转字符串 II 给定一个字符串 s 和一个整数 k&#xff0c;从字符串开头算起&#xff0c;每计数至 2k 个字符&#xff0c;就反转…

Spring,注解开发

Spring是一个轻量级的控制反转&#xff08;IOC&#xff09;和面向切面编程&#xff08;AOP&#xff09;的框架 1、组成 spring七大模块详解 2、IOC理论推导 传统的开发 (pojo层、DAO层和业务层&#xff09; &#xff08;1&#xff09;UserDao &#xff08;2) UserDaoImpl (3)…

天狼星-大熊座 Ursa Major SIRIUS

大熊座 Ursa Major SIRIUS 键盘说明 客制化键盘&#xff1a; 大熊座 Ursa Major SIRIUS 配列&#xff1a; 75 键帽&#xff1a;KCA-HelloWorld-Black 双模&#xff1a; 蓝牙-分裂方案 驱动配置&#xff1a;Link Lab 驱动设置软件 键盘操作 键盘说明参考&#xff1a;键位配…