Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Bounded thread queues: separate FIFO removal from task completion

Last updated: 3 Oct 20269 min read
tutorial
IntermediateBy AITrove Editorial

A bounded thread queue coordinates producers and consumers with a FIFO item order and a maximum count of waiting items. In Python, queue.Queue provides synchronized put and get operations; a full queue can block a producer or raise Full for a nonblocking attempt. Removing an item does not mark the task complete: a consumer calls task_done after processing, and join waits for that unfinished-task count to reach zero. This is an in-process concurrency primitive. It does not persist work, retry failed jobs, or provide a distributed acknowledgment protocol. Locking also changes latency under contention, so an O(1) endpoint storage operation is not a wall-clock completion guarantee.

Operational case

A repair dispatcher has two waiting slots, preloaded with J-47 and J-52. A nonblocking attempt to add J-61 reports backpressure instead of silently discarding a job. One worker processes the two queued jobs and acknowledges each after appending it to its local result list. The main thread waits for the unfinished count and then for the worker to exit. Only one consumer runs here, so result order matches FIFO. With several workers, dequeue order remains defined, but completion order can differ; callers must not assume the printed order would remain identical.

Working Python program

python
from queue import Full, Queue
from threading import Thread

repair_queue = Queue(maxsize=2)
repair_queue.put("J-47")
repair_queue.put("J-52")
try:
    repair_queue.put_nowait("J-61")
except Full:
    print("backpressure")

processed = []
def repair_worker():
    for _ in range(2):
        job_id = repair_queue.get()
        try:
            processed.append(job_id)
        finally:
            repair_queue.task_done()

worker = Thread(target=repair_worker)
worker.start()
repair_queue.join()
worker.join()
print(processed)

Output

Output
backpressure
['J-47', 'J-52']

Time, space, and tradeoff

Queue capacity bounds waiting items at O(c) space for capacity c, excluding items already held by workers. Endpoint enqueue and dequeue use constant-time underlying operations in ordinary conditions, but lock acquisition and blocking waits have workload-dependent latency. The sample uses a known two-task count so the worker can exit; a long-running service needs a sentinel, cancellation, or shutdown contract. Calling task_done in a finally block prevents join from hanging, but it does not mean a failed job succeeded. A real worker must separately record failures and decide whether and how to retry.

Common Mistakes

  • Do not treat get as an acknowledgment of successful processing.
  • Do not read qsize and assume the next put or get cannot block.
  • Do not mistake an in-process queue for durable delivery.

Connected lessons

Apply it: Project: own a maintenance index and work queue and Index and queue invariants.

Bounded queues: close, wake waiters, and drain accepted work extends this operational boundary.

data structures
range-query-structures
Storage details