在Python中进行多线程处理时queue.Queue的正确实现

时间:2015-02-01 00:27:14

标签: python multithreading

我正在学习python并编写了一些简单的脚本来给自己提供各种主题的实例。其中一个是这个脚本,用于演示queue.Queue()如何与threading.Thread()一起使用来创建后台工作者。虽然这很奇怪。我跑了一些时间试验。只需要一个线程,就像你期望的那样......每个任务花费大约2秒钟(实际上只是在??)40秒内完成20个任务。有四个线程,它会再次像您期望的那样。它一次完成4个任务,因此大约需要10秒。那么当我运行20个线程时,地球如何需要0.01秒(1 s.f.)---当然它必须花费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)

1 个答案:

答案 0 :(得分:4)

你实际上并没有阻止主线程的进展:

“正确”(*)方式是通过连接所有线程来确保所有线程都已完成:

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的模块级别中有一个全局变量,因此当您要测试不同的配置时,只需要更改一个位置。