JavaScript如何为递归函数实现多线程并发且避免重复执行
JS 多线程并行执行函数+去重方案
首先明确:JavaScript 主线程为单线程,要实现真正的并行执行,需要依托 Web Worker(浏览器环境)或 worker_threads(Node.js 环境)实现,以下是可直接复用的实现方案,支持自定义线程数、自动去重已处理数字。
核心设计思路
- 用可配置容量的线程池管理并行执行单元,可直接调整参数设置为3~4个线程
- 维护全局共享的已处理数字标记集合,线程领取任务前先校验是否已被处理,避免重复执行
- 用任务队列托管所有待执行的数字,空闲线程自动领取新任务执行
代码实现示例(Node.js 环境)
依托 worker_threads 模块实现,代码如下:
const { Worker, isMainThread, parentPort, threadId } = require('worker_threads'); // 配置项:可按需自定义调整 const THREAD_COUNT = 4; // 线程数量,可修改为3/4 const MAX_NUMBER = 10; // 原逻辑的终止阈值 const processedNumbers = new Set(); // 已处理数字标记集合 const taskQueue = Array.from({length: MAX_NUMBER}, (_, i) => i + 1); // 待处理数字队列1~10 let activeWorkers = 0; // 你原有的业务逻辑 function processNumber(num) { console.log(`线程${threadId} 处理数字:${num}`); // 其他业务逻辑写在这里 } if (isMainThread) { // 初始化线程池 for (let i = 0; i < THREAD_COUNT; i++) { const worker = new Worker(__filename); activeWorkers++; // 监听worker处理完成消息 worker.on('message', (processedNum) => { processedNumbers.add(processedNum); // 分配下一个待处理任务 if (taskQueue.length > 0) { const nextNum = taskQueue.shift(); if (!processedNumbers.has(nextNum)) { worker.postMessage(nextNum); } } else { // 无任务时销毁空闲worker worker.terminate(); activeWorkers--; if (activeWorkers === 0) { console.log('所有数字处理完成'); } } }); // 给新启动的worker分配第一个任务 if (taskQueue.length > 0) { worker.postMessage(taskQueue.shift()); } } } else { // worker线程执行逻辑 parentPort.on('message', (num) => { processNumber(num); parentPort.postMessage(num); }); }
代码实现示例(浏览器环境)
浏览器端依托 Web Worker 实现,逻辑和Node.js基本一致:
主线程代码
// 配置项 const THREAD_COUNT = 3; const MAX_NUMBER = 10; const processedNumbers = new Set(); const taskQueue = Array.from({length: MAX_NUMBER}, (_, i) => i + 1); let activeWorkers = 0; for (let i = 0; i < THREAD_COUNT; i++) { const worker = new Worker('worker.js'); activeWorkers++; worker.onmessage = (e) => { processedNumbers.add(e.data); if (taskQueue.length > 0) { const nextNum = taskQueue.shift(); if (!processedNumbers.has(nextNum)) { worker.postMessage(nextNum); } } else { worker.terminate(); activeWorkers--; if (activeWorkers === 0) console.log('所有数字处理完成'); } }; if (taskQueue.length > 0) { worker.postMessage(taskQueue.shift()); } }
worker.js 独立文件代码
self.onmessage = (e) => { const num = e.data; // 你原有的业务逻辑写在这里 console.log(`处理数字:${num}`); self.postMessage(num); };
轻量场景替代方案(单线程异步并发)
如果你的业务是IO密集型(比如接口请求、文件读写),不需要CPU密集的并行计算,可直接用单线程异步并发实现,不需要引入worker,性能开销更低:
const CONCURRENCY_LIMIT = 4; // 并发数,可自定义调整 const processed = new Set(); const tasks = Array.from({length:10}, (_,i)=>i+1); let running = 0; let index = 0; // 改造后的异步业务逻辑 async function processNum(num) { if (processed.has(num)) return; processed.add(num); console.log(`处理数字:${num}`); // 其他业务逻辑写在这里 } function run() { while(running < CONCURRENCY_LIMIT && index < tasks.length) { const num = tasks[index++]; running++; processNum(num).finally(() => { running--; run(); }); } } run();
内容的提问来源于stack exchange,提问作者KazzyDev
相关产品推荐
相关产品推荐

