chatGPT的js信号量实现
信号量类
在 JavaScript 中,可以使用 Promise 和 async/await 来模拟信号量,下面是一个简单的信号量实现:
class Semaphore {
constructor(maxConcurrency) {
this.maxConcurrency = maxConcurrency;
this.currentConcurrency = 0;
this.queue = [];
}
async acquire() {
return new Promise((resolve) => {
const tryAcquire = () => {
if (this.currentConcurrency < this.maxConcurrency) {
this.currentConcurrency++;
resolve();
} else {
this.queue.push(tryAcquire);
}
};
tryAcquire();
});
}
release() {
this.currentConcurrency--;
if (this.queue.length > 0) {
const next = this.queue.shift();
next();
}
}
async withLock(task) {
await this.acquire();
try {
await task();
} finally {
this.release();
}
}
}
这个 Semaphore 类有一个构造函数,它接受一个参数 maxConcurrency,表示允许的最大并发数。acquire 方法尝试获取信号量,如果当前并发数小于最大并发数,它将立即解析。否则,它将等待直到有可用的信号量。release 方法释放信号量并唤醒等待队列中的下一个任务。withLock 方法是一个方便的包装器,它自动获取和释放信号量。
使用示例
const semaphore = new Semaphore(3); // 最大并发数为 3
async function doTask(taskId) {
console.log(`Task ${taskId} started`);
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log(`Task ${taskId} finished`);
}
async function main() {
const tasks = [];
for (let i = 0; i < 10; i++) {
tasks.push(semaphore.withLock(() => doTask(i)));
}
await Promise.all(tasks);
}
main();
在这个例子中,创建了一个信号量,最大并发数为 3。然后定义了一个异步函数 doTask,它模拟一个耗时的任务。在 main 函数中,创建了 10 个任务,并使用 withLock 方法确保最多只有 3 个任务同时运行。最后,等待所有任务完成。