线程池是如何工作的,以及如何在像 NodeJS 这样的 async/await 环境中实现它?

2024-03-08

我需要运行一个函数int f(int i)有 10_000 个参数,由于 I/O 时间的原因,执行大约需要 1 秒。
在像Python这样的语言中,我可以使用线程(或者async/await,我知道,但是我稍后会谈到)来并行化这个任务。
如果我想始终有 10 个正在运行的线程,并在它们之间分配任务,我可以使用线程池 https://stackoverflow.com/questions/3033952/threading-pool-similar-to-the-multiprocessing-pool :

def f(p):
    x = [...]
    return x

p = ThreadPool()
xs = p.map(f, range(10_000))

But 它是如何工作的?如果我想用 NodeJS 和f = http("www.google.com", callback),我应该从哪里开始?解决这类问题的算法是什么?
同样,我想同时收到 10 个请求,当一个请求完成后,下一个请求应该开始。

到目前为止我一直在想什么(很难看,因为回调正在开始对 f() 函数的新调用):

queue = ["www.google.com", "www.facebook.com"]
var f = function(url) {
  http.get(url, (e) => {
    const newUrl = queue.pop();
    f(newUrl);
  });
};

for (var i = 0; i < 10; i++) {
  f(queue.pop());
}

重新实现我链接到的 Bluebird 函数:

const mapWithConcurrency = async (values, concurrency, fn) => {
    let i = 0;
    let results = values.map(() => null);

    const work = async () => {
        while (i < values.length) {
            const current = i++;
            results[current] = await fn(values[current]);
        }
    };

    await Promise.all(Array.from({length: concurrency}, work));

    return results;
};

mapWithConcurrency(Array.from({length: 30 * 15}, (_, i) => i), 10, async i => {
    const el = document.body.appendChild(document.createElement('i'));
    el.style.left = 5 * (i % 30) + 'px';
    el.style.top = 5 * (i / 30 | 0) + 'px';
    await new Promise(resolve => { setTimeout(resolve, Math.random() * 500); });
    el.style.background = 'black';
    return 2 * i;
}).then(results => {
    console.log(results.length, results.every((x, i) => x === 2 * i));
});
i {
    background: grey;
    transition: background 0.3s ease-out;
    position: absolute;
    width: 5px;
    height: 5px;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

线程池是如何工作的,以及如何在像 NodeJS 这样的 async/await 环境中实现它? 的相关文章

随机推荐