[b0033] python 归纳 (十八)_队列Queue在多线程中使用(二)

# -*- coding: UTF-8 -*-
"""
多线程同时读队列
使用 join(), task_done()

逻辑:
    3个子线程并发 从有6个数据的队列中取数据,并且打印出来。
    主线程等待队列空了才结束

总结:
    1、主线程 调用 q.join()等待队列为空时,应该不是根据 q.qsize()判断的
      也就是在Queue设计上,q.qsize()操作的内部队列大小变量 和 task_done()操作的内部队列大小变量
      不是同一个

使用:
    1、正常创建队列,往队列中读写数据
    2、在线程处理完一个队列数据后加上  q.task_done()
    3、在主线程中执行  q.join()

资料:
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
Queue.join() 实际上意味着等到队列为空,再执行别的操作
如果线程里每从队列里取一次,但没有执行task_done(),则join无法判断队列到底有没有结束,在最后执行个join()是等不到结果的,会一直挂起。
可以理解为,每task_done一次 就从队列里删掉一个元素,这样在最后join的时候根据队列长度是否为零来判断队列是否结束,从而执行主线程。

"""
import Queue
import threading
import time
import random

q = Queue.Queue(0) # 无限大小的队列
NUM_WORKERS = 3    # 线程数量

class MyThread(threading.Thread):
    """从队列读取数据打印"""

    def __init__(self,queue,threadid):
       """
        :param queue:     队列
        :param threadid:  线程编号
       """
       threading.Thread.__init__(self)
       self._jobq = queue
       self._threadid = threadid

    def run(self):

        ## 每个子线程不断从队列中读取数据,知道队列空才结束
        while True:
            time.sleep( random.random()*5)
            # 获取队列数据
            data = None

            try:
                data = self._jobq.get(False) # 队列空,抛出异常
            except:
                break

            ## 效果同上
            # if  self._jobq.qsize()>0:
            #     data = self._jobq.get()
            # else:
            #     break

            print "doing", data, " sub_process ", self._threadid
            self._jobq.task_done() #  执行发送信号  告诉执行join()等待的线程,队列中又少了一个数据啦

        print "sub_process end:",self._threadid


if __name__ == '__main__':
    print "begin...."
    # 往队列写数据
    for i in range(NUM_WORKERS * 2):
       q.put(i)

    print "job qsize:",q.qsize()

    # 启动线程
    for x in range(NUM_WORKERS):
       MyThread(q,x).start()

    q.join()    # 主线程等待队列空,子线程执行一次task_done(),它就知道队列大小减一了
    print "end"

"""
Out:
begin....
job qsize: 6
doing 0  sub_process  1
doing 1  sub_process  0
doing 2  sub_process  1
doing 3  sub_process  2
doing 4  sub_process  2
doing 5  sub_process  0
end
sub_process end: 1
sub_process end: 2
sub_process end: 0
"""

 

posted @ 2018-09-11 22:30  sunzebo  阅读(212)  评论(0编辑  收藏  举报