···5050});
5151```
52525353-### `workers(size)`
5353+### `workers(size?, opts?)`
54545555-Creates a pool of worker threads. Returns a `Runner` that dispatches tasks with round-robin scheduling. Disposable via `using` or `[Symbol.dispose]()`. Defaults to `os.availableParallelism()` workers when `size` is omitted.
5555+Creates a pool of worker threads. Returns a `Runner` that dispatches tasks. Disposable via `using` or `[Symbol.dispose]()`. Defaults to `os.availableParallelism()` workers and round-robin scheduling when arguments are omitted.
56565757```ts
5858import { workers } from 'moroutine';
···9090 // ...
9191}
9292```
9393+9494+#### Load Balancing
9595+9696+The pool uses round-robin scheduling by default. Pass a `balance` option to change the strategy:
9797+9898+```ts
9999+import { workers, leastBusy } from 'moroutine';
100100+101101+{
102102+ using run = workers(4, { balance: leastBusy() });
103103+ // tasks dispatched to whichever worker has the fewest in-flight tasks
104104+}
105105+```
106106+107107+Built-in balancers:
108108+- `roundRobin()` — cycles through workers in order (default)
109109+- `leastBusy()` — picks the worker with the lowest active task count
110110+111111+Custom balancers implement the `Balancer` interface:
112112+113113+```ts
114114+import type { Balancer } from 'moroutine';
115115+116116+const myBalancer: Balancer = {
117117+ select(workers, task) {
118118+ return workers[0]; // always use first worker
119119+ },
120120+};
121121+```
122122+123123+Each worker handle exposes `thread` (the underlying `worker_threads.Worker`) and `activeCount` for building custom strategies.
9312494125### Dedicated Workers
95126