# Współdziel kilka wątków roboczych przez NEWTHREADPOOL()

> Uruchom stałą liczbę workerów, pożycz jednego przez pool.exec(), gdy jest praca, oddaj go przez release() i pozwól innym zadaniom czekać na wolnego workera.

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: pl
Content-SHA256: 8ba1dec06ba700a47cad7eb4ed8c98ec73ef7db7346ea5e7e8c257f4cbdb92c7
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

`NEWTHREAD()` uruchamia jednego workera. Gdy wiele żądań potrzebuje tej samej ciężkiej pracy, worker na każde żądanie to za dużo, a jeden worker sprawia, że czekają na siebie bez żadnej kolejności. `NEWTHREADPOOL(name, count, [isfork])` uruchamia `count` workerów z `workers/<name>.js` (wątek; z `isfork` ustawionym na `true` proces potomny, jak `NEWFORK()`) i wydaje je po jednym.

- `pool.exec(function(worker, release) {})` czeka, aż worker będzie wolny, i wywołuje Twoją funkcję z nim. Wyślij mu pracę przez `worker.postMessage(value)`, odczytaj odpowiedź przez `worker.once('message', fn)` i **wywołaj `release()`, gdy skończysz**: worker wraca do puli, a przejmuje go następne oczekujące zadanie.
- Bez funkcji `pool.exec()` zwraca obietnicę, która rozwiązuje się z `worker` (a worker ma `worker.release()`), więc działa z `await`.
- Zadania są obsługiwane w kolejności, w jakiej o niego poprosiły. Pula nie kolejkuje wiadomości workera: w danym momencie ma go jedno zadanie.
- Pula jest też przechowywana w `F.workers[name]`. `pool.workers` to lista workerów.

Plik workera jest taki sam jak dla `NEWTHREAD()`: `NEWTHREAD()` w jego wnętrzu zwraca uchwyt z `worker.message` i `worker.postMessage()`. Tutaj każdy worker sumuje liczby i mówi, który wątek to zrobił.

```js workers/total.js
require('total5');

const worker = NEWTHREAD();

worker.message = function(message) {
	let total = 0;
	for (let i = 1; i <= message.to; i++)
		total += i;
	worker.postMessage({ to: message.to, total: total, thread: require('worker_threads').threadId });
};
```

```js controllers/total.js
exports.install = function() {
	ROUTE('GET /total/{to}/', total);
	ROUTE('GET /await/{to}/', total_await);
	ROUTE('GET /workers/', workers);
};

const pool = NEWTHREADPOOL('total', 2);

function total($) {
	pool.exec(function(worker, release) {
		worker.once('message', function(response) {
			release();
			$.json(response);
		});
		worker.postMessage({ to: +$.params.to });
	});
}

async function total_await($) {
	const worker = await pool.exec();
	worker.once('message', function(response) {
		worker.release();
		$.json(response);
	});
	worker.postMessage({ to: +$.params.to });
}

function workers($) {
	$.json({ workers: pool.workers.length, registered: F.workers.total === pool });
}
```
