Put the pieces together once and the tool is reusable. A queue, a worker count, a limit per wait, and a report of what arrived is the whole shape.
What you will see
end
About 2 min of reading
Quick check
Before this new lesson, one small question about the lesson you just finished. Recall it, do not look it up.
Try It
Check the finished tool.
1
Queue drained.
import queue
q = queue.Queue()
for n in range(4):
q.put(n)
while not q.empty():
q.get()
print(q.qsize())
Before you run it, say out loud what it will print. Then open the answer.
What it prints
0
2
Parts counted.
parts = ["queue", "workers", "limits", "report"]
print(len(parts))
Before you run it, say out loud what it will print. Then open the answer.
What it prints
4
3
Tally exact.
import threading
lock = threading.Lock()
arrived = 0
def note():
global arrived
with lock:
arrived = arrived + 1
for _ in range(3):
note()
print(arrived)
Before you run it, say out loud what it will print. Then open the answer.
What it prints
3
4
Sentinel ends.
import queue
q = queue.Queue()
q.put("job")
q.put(None)
item = q.get()
while item is not None:
item = q.get()
print("end")
Before you run it, say out loud what it will print. Then open the answer.
What it prints
end
Put it in order
Before you write anything, put these lines back in the right order. Click a line to move it up one step. This support step is easier than writing code from scratch, and it is here to make the last example stick.
Data Flow
Work goes on a queue, workers drain it, each wait has a limit, a tally is kept under a lock, and a report states what arrived.
1put work on the queue
↓
2workers drain it
↓
3each wait has a limit
↓
4report what arrived
Line by line
Read the first example one line at a time. A line that prints shows what appears on screen; the rest set things up quietly.
import queuesets nothing on screen
q = queue.Queue()sets nothing on screen
for n in range(4):sets nothing on screen
q.put(n)sets nothing on screen
while not q.empty():sets nothing on screen
q.get()sets nothing on screen
print(q.qsize())0
Why this worksFour parts, four questions
The queue asks what the work is, the workers ask how many, the limits ask how long, and the report asks what arrived. A stall answers one of those.
One shared cell left
A tool with one shared tally is nearly race free. Every extra shared cell is another window to argue about.
Examples
The worker pool
import queue
import threading
q = queue.Queue()
for n inrange(4):
q.put(n)
defworker():
while not q.empty():
q.get()
workers = [threading.Thread(target=worker) for _ inrange(2)]
for w in workers:
w.start()
for w in workers:
w.join()
print(q.qsize())
Two workers drain one queue. The worker count is a dial, not a rewrite.