Python多線程-Event(事件對象)

Event

事件對象管理一個內部標誌,經過set()方法將其設置爲True,並使用clear()方法將其設置爲Falsewait()方法阻塞,直到標誌爲True。該標誌初始爲Falsepython

方法:
is_set()
當且僅當內部標誌爲True時返回True安全

set()
將內部標誌設置爲True。全部等待它成爲True的線程都被喚醒。當標誌保持在True的狀態時,線程調用wait()是不會阻塞的。併發

clear()
將內部標誌重置爲False。隨後,調用wait()的線程將阻塞,直到另外一個線程調用set()將內部標誌從新設置爲True線程

wait(timeout=None)
阻塞直到內部標誌爲真。若是內部標誌在wait()方法調用時爲True,則當即返回。不然,則阻塞,直到另外一個線程調用set()將標誌設置爲True,或發生超時。
該方法老是返回True,除非設置了timeout併發生超時。code

生產者與消費之--Event版

# -*- coding:utf-8 -*-
import threading
import time
import queue


event = threading.Event()
goods = queue.Queue(5)
num = 0


class Producer(threading.Thread):
    def run(self):
        global num
        while True:
            if goods.empty():
                event.clear()
                for _ in range(5):
                    goods.put('商品-' + str(num))
                    print('生產了商品-{0}.'.format(str(num)))
                    num += 1
                    time.sleep(1)
                event.set()


class Customer(threading.Thread):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.money = 7

    def run(self):
        while self.money:
            event.wait()
            self.money -= 1
            print('{0} 買了一個{1}.'.format(
                threading.current_thread().name, goods.get()))
            time.sleep(1)
        print('{0}沒錢了,回家.'.format(threading.current_thread().name))


if __name__ == '__main__':
    p = Producer(daemon=True)
    c1 = Customer(name='Alice')
    c2 = Customer(name='Bob')
    c2.start()
    p.start()
    c1.start()
    c1.join()
    c2.join()

運行結果:orm

生產了商品-0.
生產了商品-1.
生產了商品-2.
生產了商品-3.
生產了商品-4.
Alice 買了一個商品-0.
Bob 買了一個商品-1.
Alice 買了一個商品-2.
Bob 買了一個商品-3.
Alice 買了一個商品-4.
生產了商品-5.
生產了商品-6.
生產了商品-7.
生產了商品-8.
生產了商品-9.
Alice 買了一個商品-5.
Bob 買了一個商品-6.
Alice 買了一個商品-7.
Bob 買了一個商品-8.
生產了商品-10.
Alice 買了一個商品-9.
生產了商品-11.
生產了商品-12.
生產了商品-13.
生產了商品-14.
Alice 買了一個商品-10.
Bob 買了一個商品-11.
Alice沒錢了,回家.
Bob 買了一個商品-12.
Bob 買了一個商品-13.
Bob沒錢了,回家.

這裏會出現一種特殊狀況,當消費者線程較多時會大量出現:對象

生產了商品-0.
生產了商品-1.
生產了商品-2.
生產了商品-3.
生產了商品-4.
Bob 買了一個商品-0.
Alice 買了一個商品-1.
Bob 買了一個商品-2.
Alice 買了一個商品-3.
Bob 買了一個商品-4.
生產了商品-5.                    # !!!!!
Alice 買了一個商品-5.             # !!!!!
生產了商品-6.
生產了商品-7.
生產了商品-8.
生產了商品-9.
Bob 買了一個商品-6.
Alice 買了一個商品-7.
Alice 買了一個商品-8.
Bob 買了一個商品-9.
生產了商品-10.
生產了商品-11.
生產了商品-12.
生產了商品-13.
生產了商品-14.
Alice 買了一個商品-10.
Bob 買了一個商品-11.
Bob 買了一個商品-12.
Alice 買了一個商品-13.
Bob沒錢了,回家.
Alice沒錢了,回家.

這是由於生產者在輪詢檢查商品是否爲空會有很小的延遲,在這個延遲中有消費者線程正好跑過了wait()方法,而阻塞在了商品獲取這裏(商品使用了隊列,隊列是線程安全的,當隊列爲空時,get()方法會阻塞),因此當生產者開始執行的時候,這個消費者由於商品隊列裏有數據就被當即喚醒了。隊列

相關文章
相關標籤/搜索