簡體   English   中英

在Python中進行多線程處理時queue.Queue的正確實現

[英]The correct implementation of queue.Queue when multithreading in Python

我正在學習python並編寫了一些簡單的腳本來給自己提供各種主題的實例。 其中一個是這個腳本,用於演示queue.Queue()如何與threading.Thread()一起使用來創建后台工作者。 雖然這很奇怪。 我跑了一些時間試驗。 只需要一個線程,就像你期望的那樣......每個任務花費大約2秒鍾(實際上只是在??)40秒內完成20個任務。 有四個線程,它會再次像您期望的那樣。 它一次完成4個任務,因此大約需要10秒。 那么當我運行20個線程時,地球如何需要0.01秒(1平方英尺) - 當然它必須花費2秒???

這是代碼:

import threading
from queue import Queue
import time

q = Queue()
tLock = threading.Lock()

def run() :

    while True :
        task = q.get()  
        print('Just finished task number',task)
        q.task_done()   
        time.sleep(2)

def main() :
    # worker threads are activated  
    for x in range(20) :
        t = threading.Thread(target=run)
        t.daemon = True
        t.start()
    #20 jobs are put in the queue   
    for x in range(1,21) :
        q.put(x)
    #waits until queue is empty and then continues
    q.join()

if __name__ == '__main__' :
    startTime = time.time()
    main()
    print('Time taken was', time.time() - startTime)

你實際上並沒有阻止主線程的進度:

“正確”(*)方法是通過連接所有線程來確保所有線程都已完成:

def main() :
    # keep reference to threads
    threads = [threading.Thread(target=run) for _ in range(20)]
    # start all threads
    for t in threads:
        t.start()

    #20 jobs are put in the queue   
    for x in range(1,21) :
        q.put(x)
    #waits until queue is empty and then continues
    q.join()
    # join all threads
    for t in threads:
        t.join()

*但是 ,這不會起作用,因為你的線程處於無限循環中,甚至完成任務。

另一種方法是確保報告任務之前等待:

def run() :
    while True :
        task = q.get()  
        # simulate processing time *before* actual reporting
        time.sleep(2)
        print('Just finished task number',task)  
        q.task_done()

仍然,線程仍然被阻止。 你應該擁有的是給線程告訴他們退出的信息。 就像是:

def run() :
    while True :
        task = q.get()
        if task == 'stop':
            break  
        # simulate processing time *before* actual reporting
        time.sleep(2)
        print('Just finished task number',task)  
        q.task_done()

現在簡單地告訴主線程為所有線程放置足夠的停止消息以最終退出它們的無限循環:

def main() :
    # keep reference to threads
    threads = [threading.Thread(target=run) for _ in range(20)]
    # start all threads
    for t in threads:
        t.start()

    #20 jobs are put in the queue   
    for x in range(1,21):
        q.put(x)

    for x in range(20):
        # stop all threads after tasks are done
        q.put('stop')

    # waits until queue is empty and then continues
    q.join()

    # join all threads
    for t in threads:
        t.join()

提示:您不應該使用“魔術數字”,例如20 在名為THREADS_COUNT的模塊級別中有一個全局變量,因此當您要測試不同的配置時,只需要更改一個位置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM