Effective Python 读书笔记: 第39条: 用Queue来协调各线程之间的工作

# -*- encoding: utf-8 -*-

from collections import deque
from queue import Queue
from threading import Lock
from threading import Thread
from time import sleep

'''
第39条: 用Queue来协调各线程之间的工作

关键:
1 管线将处理流程划分为几个节点,用多个线程同时执行任务
2 要注意防止某个阶段先入等待中
3 Queue类具备阻塞式操作,指定队列大笑,支持join方法
4 样例:
    downloadQueue = ClosableQueue()
    resizeQueue = ClosableQueue()
    uploadQueue = ClosableQueue()
    doneQueue = ClosableQueue()
    threads = [
        StoppableWorker(download, downloadQueue, resizeQueue),
        StoppableWorker(resize, resizeQueue, uploadQueue),
        StoppableWorker(upload, uploadQueue, doneQueue)
    ]
    for thread in threads:
        thread.start()
    for _ in range(1000):
        downloadQueue.put(object())
    downloadQueue.close()
    downloadQueue.join()

参考:
Effectiv Python 编写高质量Python代码的59个有效方法
'''

class MyQueue(object):
    def __init__(self):
        self.items = deque()
        self.lock = Lock()

    def put(self, item):
        with self.lock:
            self.items.append(item)

    def get(self):
        with self.lock:
            return self.items.popleft()


'''
作用:
用线程表示管线的各个阶段,Worker线程会从队列中取出任务,并对该任务
运行相关函数,把运行结果放到另一个队列中
'''
class Worker(Thread):
    def __init__(self, func, inQueue, outQueue):
        super(Worker, self).__init__()
        self.func = func
        self.inQueue = inQueue
        self.outQueue = outQueue
        self.polledCount = 0
        self.workDone = 0

    def run(self):
        while True:
            self.polledCount += 1
            try:
                item = self.inQueue.get()
            except IndexError:
                sleep(0.1)
            else:
                result = self.func(item)
                self.outQueue.put(result)
                self.workDone += 1

def download(value):
    pass


def resize(value):
    pass


def upload(value):
    pass


def task():
    downloadQueue = MyQueue()
    resizeQueue = MyQueue()
    uploadQueue = MyQueue()
    doneQueue = MyQueue()
    threads = [
        Worker(download, downloadQueue, resizeQueue),
        Worker(resize, resizeQueue, uploadQueue),
        Worker(upload, uploadQueue, doneQueue)
    ]
    for thread in threads:
        thread.start()
    for _ in range(1000):
        downloadQueue.put(object())
    for thread in threads:
        thread.join()
    # while len(doneQueue.items) < 1000:
    #     a = 1


queue = Queue()

def consumer2():
    print "Consumer waiting"
    queue.get()
    print "Consumer done"


def consumer():
    sleep(0.1)
    queue.get()
    print "Consumer got 1"
    queue.get()
    print "Consumer got 2"


def queueTask():
    thread = Thread(target=consumer)
    thread.start()


def queueTask2():
    thread = Thread(target=consumer)
    thread.start()
    print "Producer putting"
    queue.put(object())
    thread.join()
    print "Producer done"


class ClosableQueue(Queue):
    FINISH = object()

    def close(self):
        self.put(self.FINISH)

    def __iter__(self):
        while True:
            item = self.get()
            try:
                if item is self.FINISH:
                    return
                yield item
            finally:
                self.task_done()


class StoppableWorker(Thread):
    def __init__(self, func, inQueue, outQueue):
        super(StoppableWorker, self).__init__()
        self.func = func
        self.inQueue = inQueue
        self.outQueue = outQueue
        self.polledCount = 0
        self.workDone = 0

    def run(self):
        for item in self.inQueue:
            result = self.func(item)
            self.outQueue.put(result)


def betterQueueTask():
    downloadQueue = ClosableQueue()
    resizeQueue = ClosableQueue()
    uploadQueue = ClosableQueue()
    doneQueue = ClosableQueue()
    threads = [
        StoppableWorker(download, downloadQueue, resizeQueue),
        StoppableWorker(resize, resizeQueue, uploadQueue),
        StoppableWorker(upload, uploadQueue, doneQueue)
    ]
    for thread in threads:
        thread.start()
    for _ in range(1000):
        downloadQueue.put(object())
    downloadQueue.close()
    downloadQueue.join()
    resizeQueue.close()
    resizeQueue.join()
    uploadQueue.close()
    uploadQueue.join()
    print "doneQueue.qsize: {value} items finished".format(
        value=doneQueue.qsize()
    )
    # for thread in threads:
    #     thread.join()


def process():
    # task()
    betterQueueTask()


if __name__ == "__main__":
    process() 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值