js如何实现多线程,通过web worker实现多线程

1.什么是多线程

多线程是指在一个进程中同时执行多个线程的技术。线程是程序执行的基本单位,多个线程可以共享同一进程的资源(如内存、文件 等),并且可以并发执行,从而提高程序的效率和响应能力。

2.为什么用多线程

  1. 并发执行:多线程允许程序的多个部分同时运行,从而提高程序的执行效率,尤其是在多核处理器上。

  2. 资源共享:同一进程中的多个线程可以共享内存和资源,这使得线程之间的通信和数据交换比进程之间更高效。

  3. 响应性:在用户界面应用程序中,使用多线程可以使程序在执行长时间运行的任务时仍然保持响应,避免界面冻结。

  4. 任务分解:复杂的任务可以被分解成多个较小的子任务,并由不同的线程并行处理,从而加快整体处理速度。

  5. 提高性能:在某些情况下,特别是 I/O 密集型和计算密集型任务中,多线程可以显著提高程序的性能。

    多线程编程也带来了复杂性,例如:

  • 同步问题:多个线程同时访问共享资源时,可能会出现竞争条件,导致数据不一致。需要使用锁、信号量等机制来控制线程之间的访问。

  • 死锁:当两个或多个线程相互等待对方释放资源时,可能导致程序无法继续执行。

  • 调试困难:多线程程序的调试相对复杂,因为线程的执行顺序可能会影响程序的行为。

Web Worker

Web Workers 是一种在浏览器中运行 JavaScript 的机制,允许你在后台线程中执行代码,从而避免阻塞主线程(也就是用户界面线程)。这使得 Web Workers 特别适合处理耗时的计算任务或 I/O 操作,而不会影响用户体验。

1.原理

  1. 线程模型

  • 主线程与 Worker 线程:Web Worker 在浏览器中创建一个独立的线程(Worker 线程),与主线程(UI 线程)分离。主线程负责处理用户界面和用户交互,而 Worker 线程用于执行耗时的计算或任务。

  1. 创建 Worker

  • Worker 实例化:通过 new Worker('worker.js') 创建一个 Worker 实例,worker.js 是包含要在 Worker 中执行的 JavaScript 代码的文件。Worker 代码在独立的全局上下文中运行。

  1. 事件驱动

  • 消息传递:主线程与 Worker 之间通过消息传递进行通信。使用 postMessage() 方法将数据发送到 Worker,Worker 通过 onmessage 事件接收消息,并可以通过 postMessage() 将结果返回给主线程。

  1. 数据传递

  • 克隆与传递:通过结构化克隆算法,主线程和 Worker 之间传递的数据会被克隆,而不是直接共享。这意味着 Worker 中的数据与主线程中的数据是独立的,避免了数据竞争和并发问题。

  1. 事件循环与调度

  • 事件循环:Worker 线程也有自己的事件循环机制。当 Worker 执行完任务后,会将结果通过消息传递回主线程,主线程在空闲时会处理这些消息。

  1. 错误处理

  • 错误捕获:Worker 中的错误不会直接影响主线程。可以通过 onerror 事件处理 Worker 中的错误,确保主线程能够正常运行。

  1. 限制与安全

  • 安全性:Worker 不能直接访问 DOM、Window 对象或其他主线程的全局对象,确保了线程之间的隔离性和安全性。

     主:

     let work = new Worker('./worker.js')
     work.onmessage = e => {
          console.log(e.data)
      }

   worker.js:

function fb(n){
    if(n==1 ||n==2){
        return 1
    }
    return fb(n-1) + fb(n-2)
}

console.time('1')
let result=fb(43)
console.timeEnd('1')

self.postMessage('worker')

注释:可以通过console.time()和console.timeEnd()来计算运行时间,上面代码结果

2.特点和优势

  • 独立运行:Web Worker在一个独立的线程中运行,与主线程互不干扰。这可以避免主线程因执行耗时操作而卡顿,从而提高页面的响应速度和用户体验。

    • 隔离机制:Web Worker无法直接访问或操作DOM元素。这种隔离机制可以防止潜在的页面修改和恶意攻击,确保网页的安全性和稳定性。

    • 多线程异步执行: Web Worker允许您在标签页进程中创建多个独立线程,每个线程都可以在不同的内核上执行,因此可以实现并行计算。

    • 并行执行:Web Workers 允许你在独立的线程中执行 JavaScript 代码,这样可以实现并行处理,提高应用程序的性能。

    • 非阻塞:由于 Worker 在后台线程中运行,主线程可以继续处理用户输入和其他任务,保持应用程序的响应性。

    • 消息传递:Web Workers 通过消息传递进行通信。主线程和 Worker 之间不能直接共享变量,而是通过 postMessage 方法发送消息,并通过 onmessage 事件接收消息。

    • 没有 DOM 访问:Web Workers 不能直接访问 DOM,这样可以避免线程安全问题。它们只能通过消息与主线程进行交互。

    • 错误处理:Web Workers 可以独立于主线程处理错误,使用 onerror 事件捕获 Worker 中的错误。

注意:

报错:Uncaught SecurityError: Failed to construct 'Worker': Script at 'file:///...' cannot be accessed from origin 'null'

表示 Web Worker 无法被加载,因为它的来源被认为是 null。这是因为你是在本地文件系统(即使用 file:// 协议)中打开 HTML 文件,而不是通过 HTTP/HTTPS 服务器。

分配给Worker 线程运行的脚本文件(worker.js),必须与主线程的脚本文件(main.js)同源。这里的同源限制包括协议、域名和端口,不支持本地地址(file://)。这会带来一个问题,我们经常使用CDN来存储js文件,主线程的worker.js的域名指的是html文件所在的域,通过new Worker(url)加载的url属于CDN的域,会带来跨域的问题,实际开发中我们不会吧所有的代码都放在一个文件中让子线程加载,肯定会选择模块化开发。通过工具或库把代码合并到一个文件中,然后把子线程的代码生成一个文件url。

file:// 协议是用于访问本地文件系统的 URI(统一资源标识符)协议。当你在浏览器中打开一个本地文件(例如 HTML 文件)时,浏览器会使用 file:// 协议来访问该文件。而Web Workers 不能从 file:// 协议加载,因为这样做可能会引发安全风险。

解决:

1.

使用 VS Code 的 Live Server 插件**:

  • 安装 Live Server 插件。

  • 右键单击你的 HTML 文件,选择 "Open with Live Server"。

2.

(1)将动态生成的脚本转换成Blob对象。

(2)然后给这个Blob对象创建一个URL。

(3)最后将这个创建好的URL作为地址传给Worker的构造函数

        // let script = 'console.log(324)'
        // let workerBlob = new Blob([script], { type: "text/javascript" });
        // let url = URL.createObjectURL(workerBlob);
        // let worker = new Worker(url);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值