Очереди вы можете реализовать множеством способов. Для одного компьютера модуль стандартной библиотеки multiprocessing (с которым вы можете познакомиться в разделе «Программы и процессы» главы 10) содержит функцию Queue. Симулируем процессы одного мойщика посуды и одного сушильщика (кто-то может отложить посуду в сторону позже), а также промежуточную очередь dish_queue. Назовите эту программу dishes.py:
>import multiprocessing as mp
>def washer(dishes, output):
>····for dish in dishes:
>········print('Washing', dish, 'dish')
>········output.put(dish)
>def dryer(input):
>····while True:
>········dish = input.get()
>········print('Drying', dish, 'dish')
>········input.task_done()
>dish_queue = mp.JoinableQueue()
>dryer_proc = mp.Process(target=dryer, args=(dish_queue,))
>dryer_proc.daemon = True
>dryer_proc.start()
>dishes = ['salad', 'bread', 'entree', 'dessert']
>washer(dishes, dish_queue)
>dish_queue.join()
Запустите новую программу:
>$ python dishes.py
>Washing salad dish
>Washing bread dish
>Washing entree dish
>Washing dessert dish
>Drying salad dish
>Drying bread dish
>Drying entree dish
>Drying dessert dish
Эта очередь похожа на простой итератор, который создает набор тарелок. В действительности здесь создаются отдельные процессы, общающиеся между собой. Я использовал JoinableQueue и последний метод join(), чтобы дать знать мойщику, что вся посуда была высушена. В модуле multiprocessing существуют очереди и других типов, вы можете обратиться к документации, чтобы получить больше примеров.
Поток работает внутри процесса, имея доступ ко всему, что находится в процессе, — это похоже на раздвоение личности. Модуль multiprocessing имеет кузена по имени threading, который использует потоки вместо процессов (на самом деле модуль multiprocessing был разработан позже своего собрата, основанного на процессах). Переделаем наш пример с процессами для использования потоков:
>import threading
>def do_this(what):
>····whoami(what)
>def whoami(what):
>····print("Thread %s says: %s" % (threading.current_thread(), what))
>if __name__ == "__main__":
>····whoami("I'm the main program")
>····for n in range(4):
>········p = threading.Thread(target=do_this,
>··········args=("I'm function %s" % n,))
>········p.start()
Вот что я вижу на своем экране:
>Thread <_MainThread(MainThread, started 140735207346960)> says: I'm the main
>program
>Thread says: I'm function 0
>Thread says: I'm function 1
>Thread says: I'm function 2
>Thread says: I'm function 3