ConcurrencyPHPverifiedVerified

Thread Pool Pattern in PHP

Maintain a fixed set of reusable worker threads that pick up tasks from a queue, avoiding the overhead of spawning a new thread per task.

How to Implement the Thread Pool Pattern in PHP

1Step 1: Define the task type

interface Task
{
    public function run(): mixed;
}

2Step 2: Implement a Fiber-based thread pool

class FiberPool
{
    /** @var \Fiber[] */
    private array $fibers = [];
    /** @var Task[] */
    private array $queue = [];
    /** @var mixed[] */
    private array $results = [];
    private int $activeCount = 0;

    public function __construct(
        private readonly int $maxConcurrency,
    ) {}

    public function submit(Task $task): int
    {
        $taskId = count($this->queue);
        $this->queue[] = $task;
        return $taskId;
    }

3Step 3: Run all submitted tasks with concurrency limit

    public function run(): array
    {
        $taskIndex = 0;

        while ($taskIndex < count($this->queue) || !empty($this->fibers)) {
            // Launch new fibers up to the concurrency limit
            while ($this->activeCount < $this->maxConcurrency && $taskIndex < count($this->queue)) {
                $task = $this->queue[$taskIndex];
                $id = $taskIndex;
                $fiber = new \Fiber(function () use ($task, $id): array {
                    return ['id' => $id, 'result' => $task->run()];
                });
                $fiber->start();
                $this->fibers[$id] = $fiber;
                $this->activeCount++;
                $taskIndex++;
            }

            // Check for completed fibers
            foreach ($this->fibers as $id => $fiber) {
                if ($fiber->isTerminated()) {
                    $this->results[$id] = $fiber->getReturn();
                    unset($this->fibers[$id]);
                    $this->activeCount--;
                } elseif ($fiber->isSuspended()) {
                    $fiber->resume();
                }
            }
        }

        return $this->results;
    }
}

Thread Pool Pattern Architecture

hourglass_empty

Rendering diagram...

lightbulb

Thread Pool Pattern in the Real World

A hotel concierge desk staffed by three concierges represents the thread pool. No matter how many guests check in, only three requests are handled simultaneously. Other guests wait in the lobby queue. When a concierge finishes, they immediately assist the next waiting guest — the staff are never created or dismissed per guest, they simply stay on duty.