How does thread pooling works, and how to implement it in an async/await env like NodeJS?
Reimplementation of that Bluebird function I linked to:
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;
}
Not sure it is how ThreadPool and other libraries are implemented but here is a hint : use Queues to count how many tasks/threads are running.
I didn't try this code but it can give you an idea: we create a Thread checking every 0.2 second if we should start another Thread.
This implies a lot of context switching however and might not be efficient.
class Pool:
def __init__(self, func: Callable, params: list, thread_max = 10):
self.func = func
self.params = params
self.running = 0
self.finished = []
self.thread_max = thread_max
self.threads = []
def start(self):
Thread(target=check, args=(0.2)).start()
def check(self, t_sleep=0.5):
done = False
while not done:
sleep(t_sleep)
# first check for finished threads
for t in threads:
if not t.isAlive():
# do something with return value
# ...
self.threads.remove(t)
if not len(self.params): # mean there is no more task left to LAUNCH
done = len(self.threads) # gonna be 0 when every tasks is COMPLETE
continue # avoid the next part (launching thread)
# now start some threads if needed
while len(self.threads) < self.thread_max:
arg = self.params.pop()
thread = Thread(target=self.func, args=(arg, ))
threads.insert(thread)
thread.start()