linux

Linux中JS如何实现并发控制

小樊
41
2025-11-04 13:13:31
栏目: 编程语言

在Linux环境下,使用JavaScript进行并发控制可以通过多种方式实现,具体取决于你所使用的JavaScript运行环境(如Node.js或浏览器)。以下是几种常见的方法:

1. 使用 async/awaitPromise.all

这是最常用的并发控制方法之一,适用于Node.js和现代浏览器。通过将异步操作封装在Promise中,并使用Promise.all来并行执行多个任务,同时控制并发数量。

示例代码(限制并发数为5):

const async = require('async');

// 模拟异步任务
function asyncTask(item) {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log(`任务完成: ${item}`);
            resolve(item);
        }, 1000);
    });
}

// 控制并发数的函数
async function runTasks(tasks, concurrency) {
    const results = [];
    const executing = [];

    for (const task of tasks) {
        const p = asyncTask(task).then(result => {
            results.push(result);
            executing.splice(executing.indexOf(p), 1);
        });
        results.push(p);
        executing.push(p);

        if (executing.length >= concurrency) {
            await Promise.race(executing);
        }
    }

    await Promise.all(executing);
    return results;
}

// 使用示例
const tasks = Array.from({ length: 20 }, (_, i) => `任务${i + 1}`);
runTasks(tasks, 5).then(results => {
    console.log('所有任务完成:', results);
});

使用第三方库 p-limit

p-limit 是一个轻量级的库,用于限制并发Promise的数量。

安装:
npm install p-limit
示例代码:
const pLimit = require('p-limit');

// 模拟异步任务
function asyncTask(item) {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log(`任务完成: ${item}`);
            resolve(item);
        }, 1000);
    });
}

const limit = pLimit(5); // 限制并发数为5

const tasks = Array.from({ length: 20 }, (_, i) => `任务${i + 1}`);
const promises = tasks.map(task => limit(() => asyncTask(task)));

Promise.all(promises).then(results => {
    console.log('所有任务完成:', results);
});

2. 使用生成器(Generators)和 co

生成器函数可以与co库结合使用,以实现更简洁的并发控制。

安装 co
npm install co
示例代码:
const co = require('co');

// 模拟异步任务
function asyncTask(item) {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log(`任务完成: ${item}`);
            resolve(item);
        }, 1000);
    });
}

// 控制并发数的生成器函数
function* runTasks(tasks, concurrency) {
    const results = [];
    const queue = tasks.slice();

    while (queue.length > 0) {
        const workers = Array.from({ length: concurrency }, () => queue.shift());
        const done = yield Promise.all(workers.map(task => asyncTask(task)));
        results.push(...done);
    }

    return results;
}

co(runTasks.bind(null, Array.from({ length: 20 }, (_, i) => `任务${i + 1}`), 5)).then(results => {
    console.log('所有任务完成:', results);
});

3. 使用线程池(适用于Node.js)

Node.js原生不支持多线程,但可以使用第三方库如worker_threads来创建线程池,实现并发控制。

示例代码:
const { Worker, isMainThread, parentPort } = require('worker_threads');

if (isMainThread) {
    const numTasks = 20;
    const concurrency = 5;
    const tasks = Array.from({ length: numTasks }, (_, i) => `任务${i + 1}`);
    const workers = [];
    let completed = 0;
    const results = [];

    function runWorker() {
        if (tasks.length === 0) {
            console.log('所有任务完成:', results);
            process.exit(0);
            return;
        }
        const task = tasks.shift();
        const worker = new Worker(__filename);
        worker.postMessage(task);
        workers.push(worker);

        worker.on('message', (result) => {
            results.push(result);
            completed++;
            workers.splice(workers.indexOf(worker), 1);
            runWorker();
        });

        worker.on('error', (err) => {
            console.error(err);
            workers.splice(workers.indexOf(worker), 1);
            runWorker();
        });

        worker.on('exit', (code) => {
            if (code !== 0)
                console.error(`Worker stopped with exit code ${code}`);
            workers.splice(workers.indexOf(worker), 1);
            runWorker();
        });
    }

    runWorker();
} else {
    parentPort.on('message', async (task) => {
        // 模拟异步任务
        await new Promise(resolve => setTimeout(resolve, 1000));
        parentPort.postMessage(`完成: ${task}`);
    });
}

4. 使用事件驱动的方法

在Node.js中,可以利用事件循环和事件驱动的特性,通过自定义事件来管理并发任务。

示例代码:
const EventEmitter = require('events');

class TaskManager extends EventEmitter {
    constructor(concurrency) {
        super();
        this.concurrency = concurrency;
        this.running = 0;
        this.queue = [];
    }

    addTask(task) {
        this.queue.push(task);
        this.next();
    }

    next() {
        while (this.running < this.concurrency && this.queue.length > 0) {
            const task = this.queue.shift();
            this.running++;
            task().then(result => {
                this.emit('taskDone', result);
            }).catch(err => {
                this.emit('taskError', err);
            }).finally(() => {
                this.running--;
                this.next();
            });
        }
    }
}

// 使用示例
const taskManager = new TaskManager(5);

const tasks = Array.from({ length: 20 }, (_, i) => () => 
    new Promise((resolve) => {
        setTimeout(() => {
            console.log(`任务完成: ${i + 1}`);
            resolve(`结果${i + 1}`);
        }, 1000);
    })
);

tasks.forEach(task => taskManager.addTask(task));

taskManager.on('taskDone', result => {
    console.log('任务结果:', result);
});

taskManager.on('taskError', err => {
    console.error('任务出错:', err);
});

总结

在Linux环境下使用JavaScript进行并发控制,主要依赖于Promiseasync/await以及第三方库如p-limit等工具。选择具体的方法应根据项目需求、运行环境以及个人偏好来决定。对于Node.js,还可以利用多线程或事件驱动的方法来实现更复杂的并发控制。

0
看了该问题的人还看了