JavaScript 多线程完全指南

JavaScript 多线程完全指南

为什么需要多线程?#

JavaScript 本质上是单线程的,这意味着所有任务(UI 渲染、用户交互、JS 代码执行)都在同一个主线程上排队执行。如果一个任务耗时过长,整个页面就会被”冻结”,无法响应用户操作,造成卡顿。

想象一下这些场景:

处理大量数据计算(图像处理、加密解密)

解析大型 JSON 文件

复杂的数学运算

实时音视频处理

这些任务如果在主线程执行,用户界面就会完全失去响应。为了解决这个根本性问题,JavaScript 生态演化出了多层次的并发解决方案。

一、应用层:异步编程模式#

在真正的多线程出现之前,JavaScript 通过事件循环和异步编程来”模拟”并发,让耗时操作不阻塞主线程。

1.1 基础异步 API#

// setTimeout/setInterval - 延迟执行

setTimeout(() => {

console.log('1秒后执行');

}, 1000);

// requestAnimationFrame - 动画优化

function animate() {

// 更新动画

requestAnimationFrame(animate);

}

// requestIdleCallback - 空闲时执行

requestIdleCallback(() => {

// 在浏览器空闲时执行低优先级任务

});javascript

1.2 Promise 和 async/await#

// Promise 链式调用

fetch('/api/data')

.then(response => response.json())

.then(data => processData(data))

.catch(error => console.error(error));

// async/await 语法糖

async function loadData() {

try {

const response = await fetch('/api/data');

const data = await response.json();

return processData(data);

} catch (error) {

console.error(error);

}

}javascript

局限性:这些方案本质上仍是单线程,只是通过事件循环让出执行权,无法真正并行计算。

二、Worker 层:真正的多线程#

浏览器引入了 Worker API,允许在独立线程中执行 JavaScript 代码,实现真正的并行计算。

2.1 Web Worker - 计算密集型任务#

Web Worker 是最基础的多线程方案,专门用于执行耗时的计算任务。

主线程代码:

// 创建 Worker

const worker = new Worker('worker.js');

// 发送数据

worker.postMessage({ data: largeArray });

// 接收结果

worker.onmessage = (e) => {

console.log('计算结果:', e.data);

};

// 错误处理

worker.onerror = (error) => {

console.error('Worker 错误:', error);

};

// 终止 Worker

worker.terminate();javascript

worker.js:

// Worker 线程代码

self.onmessage = (e) => {

const result = heavyComputation(e.data);

self.postMessage(result);

};

function heavyComputation(data) {

// 执行复杂计算

return data.map(x => x * x).reduce((a, b) => a + b);

}javascript

特点:

独立的全局作用域,无法访问 DOM

通过消息传递通信(结构化克隆)

适合 CPU 密集型任务

2.2 Shared Worker - 跨页面共享#

Shared Worker 可以被多个浏览器标签页或 iframe 共享,适合需要跨页面协调的场景。

// 多个页面可以连接同一个 Shared Worker

const worker = new SharedWorker('shared-worker.js');

worker.port.onmessage = (e) => {

console.log('收到消息:', e.data);

};

worker.port.postMessage('Hello from page');javascript

shared-worker.js:

const connections = [];

self.onconnect = (e) => {

const port = e.ports[0];

connections.push(port);

port.onmessage = (e) => {

// 广播给所有连接的页面

connections.forEach(p => p.postMessage(e.data));

};

};javascript

2.3 Service Worker - 网络代理和离线支持#

Service Worker 是一个特殊的 Worker,运行在浏览器后台,充当网络代理的角色。

// 注册 Service Worker

navigator.serviceWorker.register('/sw.js').then(registration => {

console.log('Service Worker 注册成功');

});javascript

sw.js:

// 安装阶段 - 缓存资源

self.addEventListener('install', (e) => {

e.waitUntil(

caches.open('v1').then(cache => {

return cache.addAll(['/index.html', '/style.css', '/app.js']);

})

);

});

// 拦截网络请求

self.addEventListener('fetch', (e) => {

e.respondWith(

caches.match(e.request).then(response => {

return response || fetch(e.request);

})

);

});

// 后台同步

self.addEventListener('sync', (e) => {

if (e.tag === 'sync-data') {

e.waitUntil(syncData());

}

});

// 推送通知

self.addEventListener('push', (e) => {

const data = e.data.json();

self.registration.showNotification(data.title, {

body: data.body,

icon: '/icon.png'

});

});javascript

应用场景:

PWA 离线支持

缓存策略管理

后台数据同步

推送通知

三、Worklet 层:高性能渲染管线#

Worklet 是轻量级的 Worker,专门用于浏览器渲染管线的特定阶段,性能开销更小。

3.1 Audio Worklet - 音频处理#

// 加载 Audio Worklet

await audioContext.audioWorklet.addModule('processor.js');

// 创建处理器节点

const node = new AudioWorkletNode(audioContext, 'my-processor');javascript

processor.js:

class MyProcessor extends AudioWorkletProcessor {

process(inputs, outputs, parameters) {

const input = inputs[0];

const output = outputs[0];

// 实时音频处理

for (let channel = 0; channel < output.length; channel++) {

for (let i = 0; i < output[channel].length; i++) {

output[channel][i] = input[channel][i] * 0.5; // 降低音量

}

}

return true; // 继续处理

}

}

registerProcessor('my-processor', MyProcessor);javascript

3.2 Paint Worklet - 自定义绘制#

// 注册 Paint Worklet

CSS.paintWorklet.addModule('paint.js');javascript

paint.js:

class CheckerboardPainter {

paint(ctx, size, properties) {

const colors = ['#fff', '#000'];

const squareSize = 20;

for (let y = 0; y < size.height / squareSize; y++) {

for (let x = 0; x < size.width / squareSize; x++) {

ctx.fillStyle = colors[(x + y) % 2];

ctx.fillRect(x * squareSize, y * squareSize, squareSize, squareSize);

}

}

}

}

registerPaint('checkerboard', CheckerboardPainter);javascript

CSS 使用:

.element {

background-image: paint(checkerboard);

}css

3.3 Animation Worklet - 高性能动画#

await CSS.animationWorklet.addModule('animator.js');

const animation = new WorkletAnimation(

'my-animator',

new KeyframeEffect(element, keyframes, options)

);

animation.play();javascript

四、底层:共享内存和原子操作#

对于需要极致性能的场景,JavaScript 提供了共享内存机制。

4.1 SharedArrayBuffer#

// 主线程创建共享内存

const sharedBuffer = new SharedArrayBuffer(1024);

const sharedArray = new Int32Array(sharedBuffer);

// 发送给 Worker

worker.postMessage(sharedBuffer);

// Worker 可以直接读写同一块内存

// worker.js

self.onmessage = (e) => {

const sharedArray = new Int32Array(e.data);

sharedArray[0] = 42; // 主线程可以立即看到变化

};javascript

4.2 Atomics - 原子操作#

const sharedArray = new Int32Array(sharedBuffer);

// 原子加法

Atomics.add(sharedArray, 0, 5);

// 原子比较交换

Atomics.compareExchange(sharedArray, 0, 5, 10);

// 等待通知(阻塞)

Atomics.wait(sharedArray, 0, 0);

// 唤醒等待的线程

Atomics.notify(sharedArray, 0, 1);javascript

应用场景:

多线程协调和同步

实现锁和信号量

高性能数据共享

五、WebAssembly Threads#

WebAssembly 支持真正的多线程,配合 SharedArrayBuffer 可以实现接近原生的性能。

// 加载支持多线程的 WASM 模块

const { instance } = await WebAssembly.instantiateStreaming(

fetch('module.wasm'),

{

env: {

memory: new WebAssembly.Memory({

initial: 256,

maximum: 256,

shared: true // 共享内存

})

}

}

);

// WASM 内部可以创建线程并行计算

instance.exports.parallelCompute();javascript

六、OffscreenCanvas - Worker 中的渲染#

OffscreenCanvas 允许在 Worker 中进行 Canvas 渲染,避免阻塞主线程。

主线程:

const canvas = document.getElementById('canvas');

const offscreen = canvas.transferControlToOffscreen();

const worker = new Worker('render-worker.js');

worker.postMessage({ canvas: offscreen }, [offscreen]);javascript

render-worker.js:

self.onmessage = (e) => {

const canvas = e.data.canvas;

const ctx = canvas.getContext('2d');

function render() {

// 在 Worker 中渲染

ctx.clearRect(0, 0, canvas.width, canvas.height);

ctx.fillRect(Math.random() * canvas.width, Math.random() * canvas.height, 50, 50);

requestAnimationFrame(render);

}

render();

};javascript

技术选型指南#

场景推荐方案大量数据计算Web Worker跨页面状态同步Shared Worker离线应用、PWAService Worker实时音频处理Audio Worklet自定义 CSS 效果Paint Worklet高性能动画Animation Worklet多线程数据共享SharedArrayBuffer + Atomics极致性能计算WebAssembly Threads复杂 Canvas 渲染OffscreenCanvas + Worker普通异步操作async/await

总结#

JavaScript 的多线程方案是一个分层的体系:

应用层:Promise/async 解决异步流程控制

Worker 层:Web Worker/Service Worker 实现真正并行

Worklet 层:深入渲染管线,性能更优

底层:SharedArrayBuffer 提供共享内存

WASM:接近原生的多线程性能

选择合适的方案,需要权衡开发复杂度、性能需求和浏览器兼容性。对于大多数场景,Web Worker + async/await 的组合已经足够强大。

相关推荐

中国十大混血男明星,中国十大混血男明星名字
体育比分365最新版app下载

中国十大混血男明星,中国十大混血男明星名字

📅 10-08 👁️ 2844
组策略(gpedit.msc)常用设置汇总
365bet娱乐平台官网

组策略(gpedit.msc)常用设置汇总

📅 12-19 👁️ 9758
[软件]请问各位谁有类似电脑版按键精灵软件推荐,操作上要求比较简单的。谢谢!