日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Python如何實現線程間通信

瀏覽:20日期:2022-07-15 17:49:12

問題

你的程序中有多個線程,你需要在這些線程之間安全地交換信息或數據

解決方案

從一個線程向另一個線程發(fā)送數據最安全的方式可能就是使用 queue 庫中的隊列了。創(chuàng)建一個被多個線程共享的 Queue 對象,這些線程通過使用 put() 和 get() 操作來向隊列中添加或者刪除元素。 例如:

from queue import Queuefrom threading import Thread# A thread that produces datadef producer(out_q): while True: # Produce some data ... out_q.put(data)# A thread that consumes datadef consumer(in_q): while True:# Get some data data = in_q.get() # Process the data ...# Create the shared queue and launch both threadsq = Queue()t1 = Thread(target=consumer, args=(q,))t2 = Thread(target=producer, args=(q,))t1.start()t2.start()

Queue 對象已經包含了必要的鎖,所以你可以通過它在多個線程間多安全地共享數據。 當使用隊列時,協(xié)調生產者和消費者的關閉問題可能會有一些麻煩。一個通用的解決方法是在隊列中放置一個特殊的值,當消費者讀到這個值的時候,終止執(zhí)行。例如:

from queue import Queuefrom threading import Thread# Object that signals shutdown_sentinel = object()# A thread that produces datadef producer(out_q): while running: # Produce some data ... out_q.put(data) # Put the sentinel on the queue to indicate completion out_q.put(_sentinel)# A thread that consumes datadef consumer(in_q): while True: # Get some data data = in_q.get() # Check for termination if data is _sentinel: in_q.put(_sentinel) break # Process the data ...

本例中有一個特殊的地方:消費者在讀到這個特殊值之后立即又把它放回到隊列中,將之傳遞下去。這樣,所有監(jiān)聽這個隊列的消費者線程就可以全部關閉了。 盡管隊列是最常見的線程間通信機制,但是仍然可以自己通過創(chuàng)建自己的數據結構并添加所需的鎖和同步機制來實現線程間通信。最常見的方法是使用 Condition 變量來包裝你的數據結構。下邊這個例子演示了如何創(chuàng)建一個線程安全的優(yōu)先級隊列

import heapqimport threadingclass PriorityQueue: def __init__(self): self._queue = [] self._count = 0 self._cv = threading.Condition() def put(self, item, priority): with self._cv: heapq.heappush(self._queue, (-priority, self._count, item)) self._count += 1 self._cv.notify() def get(self): with self._cv: while len(self._queue) == 0:self._cv.wait() return heapq.heappop(self._queue)[-1]

使用隊列來進行線程間通信是一個單向、不確定的過程。通常情況下,你沒有辦法知道接收數據的線程是什么時候接收到的數據并開始工作的。不過隊列對象提供一些基本完成的特性,比如下邊這個例子中的 task_done() 和 join() :

from queue import Queuefrom threading import Thread# A thread that produces datadef producer(out_q): while running: # Produce some data ... out_q.put(data)# A thread that consumes datadef consumer(in_q): while True: # Get some data data = in_q.get() # Process the data ... # Indicate completion in_q.task_done()# Create the shared queue and launch both threadsq = Queue()t1 = Thread(target=consumer, args=(q,))t2 = Thread(target=producer, args=(q,))t1.start()t2.start()# Wait for all produced items to be consumedq.join()

如果一個線程需要在一個“消費者”線程處理完特定的數據項時立即得到通知,你可以把要發(fā)送的數據和一個 Event 放到一起使用,這樣“生產者”就可以通過這個Event對象來監(jiān)測處理的過程了。示例如下:

from queue import Queuefrom threading import Thread, Event# A thread that produces datadef producer(out_q): while running: # Produce some data ... # Make an (data, event) pair and hand it to the consumer evt = Event() out_q.put((data, evt)) ... # Wait for the consumer to process the item evt.wait()# A thread that consumes datadef consumer(in_q): while True: # Get some data data, evt = in_q.get() # Process the data ... # Indicate completion evt.set()

討論

基于簡單隊列編寫多線程程序在多數情況下是一個比較明智的選擇。從線程安全隊列的底層實現來看,你無需在你的代碼中使用鎖和其他底層的同步機制,這些只會把你的程序弄得亂七八糟。此外,使用隊列這種基于消息的通信機制可以被擴展到更大的應用范疇,比如,你可以把你的程序放入多個進程甚至是分布式系統(tǒng)而無需改變底層的隊列結構。 使用線程隊列有一個要注意的問題是,向隊列中添加數據項時并不會復制此數據項,線程間通信實際上是在線程間傳遞對象引用。如果你擔心對象的共享狀態(tài),那你最好只傳遞不可修改的數據結構(如:整型、字符串或者元組)或者一個對象的深拷貝。例如:

from queue import Queuefrom threading import Threadimport copy# A thread that produces datadef producer(out_q): while True: # Produce some data ... out_q.put(copy.deepcopy(data))# A thread that consumes datadef consumer(in_q): while True: # Get some data data = in_q.get() # Process the data ...

Queue 對象提供一些在當前上下文很有用的附加特性。比如在創(chuàng)建 Queue 對象時提供可選的 size 參數來限制可以添加到隊列中的元素數量。對于“生產者”與“消費者”速度有差異的情況,為隊列中的元素數量添加上限是有意義的。比如,一個“生產者”產生項目的速度比“消費者” “消費”的速度快,那么使用固定大小的隊列就可以在隊列已滿的時候阻塞隊列,以免未預期的連鎖效應擴散整個程序造成死鎖或者程序運行失常。在通信的線程之間進行“流量控制”是一個看起來容易實現起來困難的問題。如果你發(fā)現自己曾經試圖通過擺弄隊列大小來解決一個問題,這也許就標志著你的程序可能存在脆弱設計或者固有的可伸縮問題。 get() 和 put() 方法都支持非阻塞方式和設定超時,例如:

import queueq = queue.Queue()try: data = q.get(block=False)except queue.Empty: ...try: q.put(item, block=False)except queue.Full: ...try: data = q.get(timeout=5.0)except queue.Empty: ...

這些操作都可以用來避免當執(zhí)行某些特定隊列操作時發(fā)生無限阻塞的情況,比如,一個非阻塞的 put() 方法和一個固定大小的隊列一起使用,這樣當隊列已滿時就可以執(zhí)行不同的代碼。比如輸出一條日志信息并丟棄。

def producer(q): ... try: q.put(item, block=False) except queue.Full: log.warning(’queued item %r discarded!’, item)

如果你試圖讓消費者線程在執(zhí)行像 q.get() 這樣的操作時,超時自動終止以便檢查終止標志,你應該使用 q.get() 的可選參數 timeout ,如下:

_running = Truedef consumer(q): while _running: try: item = q.get(timeout=5.0) # Process item ... except queue.Empty: pass

最后,有 q.qsize() , q.full() , q.empty() 等實用方法可以獲取一個隊列的當前大小和狀態(tài)。但要注意,這些方法都不是線程安全的。可能你對一個隊列使用 empty() 判斷出這個隊列為空,但同時另外一個線程可能已經向這個隊列中插入一個數據項。所以,你最好不要在你的代碼中使用這些方法。

以上就是Python如何實現線程間通信的詳細內容,更多關于Python 線程間通信的資料請關注好吧啦網其它相關文章!

標簽: Python 編程
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产字幕视频一区二区| 亚洲欧美日韩国产一区| 99久久九九| 成人自拍av| 免费欧美一区| 久久精品亚洲欧美日韩精品中文字幕| 国产a亚洲精品| 成年男女免费视频网站不卡| 日韩国产一区二区三区| 久久香蕉国产| 亚洲一区二区成人| 在线看片日韩| 日韩精品免费视频一区二区三区| 18国产精品| 免费在线成人| 黄色在线观看www| 欧美福利专区| 亚洲网址在线观看| 国产一区二区三区日韩精品| 亚洲乱码久久| 国产一区二区三区国产精品| 欧洲激情综合| 国产精品久久久久久久久免费高清 | 蜜臀av一区二区三区| 中文字幕av一区二区三区人| 欧美 日韩 国产一区二区在线视频| 日韩欧美精品一区| 中文字幕免费精品| 久久国产日韩| 九色精品91| 国产毛片精品| 国产精品原创| 91精品国产乱码久久久久久久 | 国产999精品在线观看| 亚洲电影有码| 亚州精品视频| 丰满少妇一区| 亚洲一区二区三区高清不卡| 91欧美极品| 日韩免费福利视频| 视频一区在线视频| 欧美国产中文高清| 久久久夜精品| 色婷婷狠狠五月综合天色拍| 嫩呦国产一区二区三区av| 免费观看久久av| 久久三级毛片| 男人的天堂亚洲一区| 四虎在线精品| 日韩成人一级| 美女尤物国产一区| 狂野欧美性猛交xxxx| 日韩一区二区三区精品视频第3页| 一二三区精品| 中文字幕一区二区三区四区久久 | 国产精品毛片aⅴ一区二区三区| 蜜桃久久久久久| 国产精选一区| 久久人人精品| 日韩精选在线| 精精国产xxxx视频在线野外| 日韩一区二区三免费高清在线观看| 成人在线免费观看91| 美国三级日本三级久久99 | 91精品在线观看国产| 日韩一区二区在线免费| 国产精品4hu.www| 国产欧美日韩免费观看| 日本国产一区| 99在线精品免费视频九九视| 国产麻豆精品| 欧美精品一二| 欧美黑人做爰爽爽爽| 亚洲在线成人| 亚洲天堂资源| 69堂免费精品视频在线播放| 亚洲一级网站| 精品网站999| 亚洲精品自拍| 免费不卡中文字幕在线| 日韩精品成人在线观看| 久久91导航| 精品中文在线| 日韩精品亚洲aⅴ在线影院| 国产一区亚洲| 日韩电影二区| 国产精品qvod| 欧美天堂在线| 亚洲人成毛片在线播放女女| 欧美特黄一级大片| 久久影院午夜精品| 另类欧美日韩国产在线| 日韩成人一级| 蜜臀av亚洲一区中文字幕| 欧美午夜精彩| 久久久久亚洲精品中文字幕| 欧美亚洲三区| 日韩精品a在线观看91| 丝袜美腿亚洲一区| 欧美日韩少妇| 婷婷亚洲五月| japanese国产精品| 久久在线电影| 久久精品1区| 日韩视频网站在线观看| 国产精品蜜芽在线观看| 久久亚洲人体| 久久国产乱子精品免费女| 久久国产88| 欧美中文字幕| 国产成人久久精品麻豆二区| 免费在线视频一区| 亚洲我射av| 日韩精品中文字幕吗一区二区 | 欧美国产极品| 欧美精品国产| 欧美精品国产| 国产午夜精品一区在线观看| 婷婷综合成人| 亚洲91精品| 欧美亚洲tv| 亚洲精品黄色| 日韩大片免费观看| 亚洲欧洲一区二区天堂久久| 一区二区国产在线| 精品女同一区二区三区在线观看| 精品无人区麻豆乱码久久久| 国产精品亚洲欧美| 国产精品美女在线观看直播| 欧美激情精品| 麻豆精品在线观看| 成人国产精品一区二区免费麻豆| 久久精品女人| 欧产日产国产精品视频| 国产精品99一区二区| 999在线观看精品免费不卡网站| 伊人影院久久| 国产精品7m凸凹视频分类| 在线综合亚洲| 男女男精品网站| 日韩一区二区三区免费视频| 亚洲久草在线| 日韩二区在线观看| 国产成人精品一区二区免费看京 | 日韩三级精品| 国产精品白丝久久av网站| 国产精品极品在线观看| 麻豆视频一区| 视频在线观看91| 亚洲精品无播放器在线播放| 亚洲欧美日韩一区在线观看| 欧美 日韩 国产一区二区在线视频 | 黄色成人精品网站| 五月天久久久| 免费精品视频在线| 三级一区在线视频先锋| 亚洲综合专区| 久久在线91| 欧美片第1页| 婷婷中文字幕一区| 欧美特黄一区| 免费在线亚洲欧美| 日本aⅴ免费视频一区二区三区| 久久蜜桃资源一区二区老牛| 日韩一区二区三区免费视频| 久久久久久色| 麻豆高清免费国产一区| 日本va欧美va瓶| 久久精选视频| 精品丝袜在线| 国产粉嫩在线观看| 亚州av日韩av| 精品国内亚洲2022精品成人| 欧洲激情综合| 国产精品啊v在线| 日韩欧美一区二区三区免费观看| 亚洲欧美久久久| 久久三级中文| 石原莉奈一区二区三区在线观看| 麻豆精品一区二区综合av| 国产综合亚洲精品一区二| 欧美午夜三级| 欧美一区二区三区激情视频| 欧美亚洲tv| 免费久久精品| 国产亚洲欧美日韩在线观看一区二区 | 麻豆国产一区| 亚洲综合日本| 久久久久免费| 一本综合精品| 九九色在线视频| 国产日韩一区二区三免费高清| 久久国产影院| 国产精品115| 在线成人直播| 精品在线网站观看| 色综合视频一区二区三区日韩| 日韩国产欧美一区二区| 91九色综合| 午夜在线视频观看日韩17c|