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

前言

最近在优化公司的一个项目,使用的就是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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Baumer工业相机堡盟工业相机如何使用BGAPISDK对两个万兆网相机进行触发同步(C#)

Baumer工业相机堡盟工业相机如何使用BGAPISDK对两个万兆网相机进行触发同步&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机BGAPISDK和触发同步的技术背景Baumer工业相机使用BGAPISDK进行双相机主从相机触发1.引用合适的类文件2.使用BGAPISDK设置主相机硬件触发从相机…

【C++】一文带你吃透C++多态

&#x1f34e; 博客主页&#xff1a;&#x1f319;披星戴月的贾维斯 &#x1f34e; 欢迎关注&#xff1a;&#x1f44d;点赞&#x1f343;收藏&#x1f525;留言 &#x1f347;系列专栏&#xff1a;&#x1f319; C/C专栏 &#x1f319;那些看似波澜不惊的日复一日&#xff0c;…

详解WEB集群服务(LNMP+Nginx+Tomcat+Rewrite重写+七层反向代理+SNAT|DNAT策略)

实战项目演练 1.问题描述2.实验操作步骤2.1 CentOS 7-1客户端配置2.2 CentOS 7-2网关服务器配置2.3 CentOS 7-8 (Web1:Tomcat服务器)2.3.1 安装Tomcat服务器2.3.2 提供四层反向代理的动态页面 2.4 CentOS 7-9 (Nginx服务器)2.4.1 安装Nginx服务2.4.2 安装MySQL服务2.4.3 安装配…

算法刷题-哈希表-两数之和

两数之和 1. 两数之和思路总结其他语言版本 1. 两数之和 力扣题目链接 给定一个整数数组 nums 和一个目标值 target&#xff0c;请你在该数组中找出和为目标值的那 两个 整数&#xff0c;并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中…

CSS基础学习--6 CSS Text(文本)

一、文本颜色 color:red; 颜色属性被用来设置文字的颜色。 颜色是通过CSS最经常的指定&#xff1a; 十六进制值 - 如: &#xff03;FF0000一个RGB值 - 如: RGB(255,0,0)颜色的名称 - 如: red body {color:red;} h1 {color:#00ff00;} h2 {color:rgb(255,0,0);} 二、文本的…

无敌!我用【C语言】手搓出了一个体系完整的【员工管理系统】还能玩游戏听音乐?(超详细,附完整源码)

博主简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的人。 博主主页&#xff1a;陈童学哦 所属专栏&#xff1a;C语言程序设计实验项目 如果本文对你有所帮助的话&#xff0c;还希望可以点赞&#x1f44d;收藏&#x1f4c2;支持一下…

【云原生 | 53】Docker三剑客之Docker Compose应用案例一:Web负载均衡

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…

React Hook入门小案例 在函数式组件中使用state响应式数据

Hook是react 16.8 新增的特性 是希望在不编写 class的情况下 去操作state和其他react特性 Hook的话 就不建议大家使用class的形式了 当然也可以用 这个他只是不推荐 我们还是先创建一个普通的react项目 我们之前写一个react组件可以这样写 import React from "react&qu…

Java ~ Reference ~ ReferenceQueue【总结】

前言 文章 相关系列&#xff1a;《Java ~ Reference【目录】》&#xff08;持续更新&#xff09;相关系列&#xff1a;《Java ~ Reference ~ ReferenceQueue【源码】》&#xff08;学习过程/多有漏误/仅作参考/不再更新&#xff09;相关系列&#xff1a;《Java ~ Reference ~ …

【前端 - CSS】第 9 课 - CSS 初体验

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、CSS 定义 2、基础选择器 3、文字控制属性 4、示例代码 5、总结 1、CSS 定义 层叠样式表&#xff08;Cascading Style …

前端vue地图定位并测算当前定位离目标位置距离

前端vue地图定位并测算当前定位离目标位置距离, 下载完整代码请访问uni-app插件市场地址: https://ext.dcloud.net.cn/plugin?id12974 效果图如下: # #### 使用方法 使用方法 <!-- // 腾讯地图key注册地址&#xff08;针对H5端&#xff0c;manifest.json中web配置&…

触发器和事件自动化的讲解

触发器和事件自动化 一、触发器 1、触发器的基本概念 触发器是和表相关的一种数据库对象&#xff0c;可以将他看作一种特殊的存储过程&#xff0c;不需要人为调动的存储过程。 关键字&#xff1a;trigger 基本作用&#xff1a;通过对表进行数据的插入、更新或删除等操作来触…

XGBoost的介绍

一、XGBoost的介绍 1.什么是XGBoost&#xff1f; XGBoost&#xff08;eXtreme Gradient Boosting&#xff09;是一种基于梯度提升树的机器学习算法&#xff0c;它在解决分类和回归问题上表现出色。它是由陈天奇在2014年开发的&#xff0c;如今已成为机器学习领域中最流行和强…

那年我头脑发热,选择了自动化,后来我掉入计算机的世界无法自拔

首先&#xff0c;小雅兰是22届高考考生&#xff0c;而且当时填报志愿也没有填报到计算机相关的专业去&#xff0c;小雅兰是自动化专业的学生&#xff0c;是由于一次偶然的机会&#xff0c;了解到了这个行业&#xff0c;对于写代码所带来的成就感&#xff0c;总之&#xff0c;我…

2023春期末考试选择题R2-9AVL树插入调整详解

题目&#xff1a; 将 8, 9, 7, 2, 3, 5, 6, 4 顺序插入一棵初始为空的AVL树。下列句子中哪句是错的&#xff1f; A. 4 和 6 是兄弟 B. 5 是 8 的父结点 C. 7 是根结点 D. 3 和 8 是兄弟 解题要点&#xff1a; 需要对AVL树的4种旋转方式熟悉。 AVL旋转过程&#xff1a; 根据…

人事管理项目-部门数据删除

人事管理项目-部门数据删除 后端实现前端实现 Spring Boot是一个框架&#xff0c;一种全新的编程规范&#xff0c;它的产生简化了框架的使用&#xff0c;所谓简化是指简化了Spring众多框架中所需的大量且烦琐的配置文件&#xff0c;所以Spring Boot是一个服务于框架的框架&…

使用IDEA使用Git:Git使用指北——实际操作篇

Git使用指北——实际操作 &#x1f916;:使用IDEA Git插件实际工作流程 &#x1f4a1; 本文从实际使用的角度出发&#xff0c;以IDEA Git插件为基座讲述了如果使用IDEA的Git插件来解决实际开发中的协作开发问题。本文从 远程仓库中拉取项目&#xff0c;在本地分支进行开发&…

电路模型和电路定律(3)——“电路分析”

小雅兰期末加油冲冲冲&#xff01;&#xff01;&#xff01; 复习之前的内容&#xff1a; 这样的连接方式是不可以的&#xff1a; 两个电压源&#xff0c;电压值不相同&#xff0c;是不能并联的 两个电流源&#xff0c;电流值不相同&#xff0c;是不能串联的 电流源也不能开…

PoseiSwap的趋势性如何体现?

DEX 代表了一种先进的意识形态&#xff0c;相对于 CEX 其更强调无许可、去中心化以及公开透明。然而随着 DeFi 赛道逐渐从 2021 年年底的高峰逐渐转向低谷&#xff0c;DEX 整体的交易量、TVL等数据指标也开始呈现下滑的趋势&#xff0c;DEX 正在面临发展的新瓶颈期。 在这样的背…

漂亮国因一颗气球而疯狂给质量团队带来的启示

最近漂亮国因为我国的一颗漂洋过海的淘气的民用气球而疯狂。这颗气球成功躲过了号称全球最先进的防空系统&#xff0c;跨越大半个漂亮国&#xff0c;直到被一居民拍照无意间发现&#xff0c;漂亮国才反应过来。多次派战斗机拦截无果&#xff0c;在气球降到15km后&#xff0c;F2…