66 lines
2.1 KiB
Python
66 lines
2.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Демо: Process + Queue — ручная организация воркеров.
|
|
|
|
Запуск из корня курса:
|
|
python lab04_multiprocessing/examples/03_process_queue_demo.py
|
|
|
|
Pool — удобный «конвейер». Process+Queue — ручная схема: воркеры сами берут
|
|
задачи из очереди. Это основа для producer-consumer в лабе 5.
|
|
"""
|
|
import multiprocessing
|
|
import os
|
|
import sys
|
|
import time
|
|
|
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
|
|
|
|
|
|
def worker(task_q, result_q):
|
|
"""Воркер: берёт задачи, пока не встретит None — «маркер конца»."""
|
|
name = multiprocessing.current_process().name
|
|
while True:
|
|
task = task_q.get()
|
|
if task is None:
|
|
result_q.put((name, "done"))
|
|
break
|
|
idx, value = task
|
|
time.sleep(0.05) # «полезная работа»
|
|
result_q.put((name, f"задача {idx}: {value}² = {value ** 2}"))
|
|
|
|
|
|
def main():
|
|
ctx = multiprocessing.get_context()
|
|
task_q = ctx.Queue()
|
|
result_q = ctx.Queue()
|
|
|
|
n_workers = 3
|
|
workers = [ctx.Process(target=worker, args=(task_q, result_q),
|
|
name=f"воркер-{i}")
|
|
for i in range(n_workers)]
|
|
for w in workers:
|
|
w.start()
|
|
|
|
# кладём задачи
|
|
for i in range(9):
|
|
task_q.put((i, i + 1))
|
|
# маркеры конца — по одному на воркер
|
|
for _ in range(n_workers):
|
|
task_q.put(None)
|
|
|
|
# собираем результаты
|
|
done = 0
|
|
t0 = time.perf_counter()
|
|
while done < n_workers:
|
|
name, msg = result_q.get()
|
|
if msg == "done":
|
|
done += 1
|
|
print(f" [{name}] завершился")
|
|
else:
|
|
print(f" [{name}] {msg}")
|
|
for w in workers:
|
|
w.join()
|
|
print(f"время: {time.perf_counter() - t0:.2f} c (9 задач по 0.05 c на 3 воркерах)")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |