Queue-----线程安全的FIFO实现

作用:提供一个线程安全的FIFO实现。

  Queue模块提供了适用于多线程编程的先进先出数据结构,可以用来在生产者和消费者线程之间安全地传递消息或其他数据。它会为调用者处理锁定,是多个线程可以安全地处理同一个Queue实例。Queue的大小(其中包含的元素个数)可能要受限,以限制内存使用或处理。

1.基本FIFO队列

  Queue类实现了一个基本的先进先出容器。使用put()将元素增加到序列一端,使用get()从另一端删除。

import queue
q = queue.Queue()
for i in range(5):
    q.put(i)
while not q.empty():
    print(q.get())

  这个例子使用了一个线程,来展示按元素的插入顺序从队列删除元素。

0
1
2
3
4

 

2.LIFO队列

  与Queue的标准FIFO实现相反,LifoQueue使用了后进先出,顺序。

q = queue.LifoQueue()
for i in range(5):
    q.put(i)
while not q.empty():
    print(q.get())

  get()将删除最近使用put插入到队列的元素。

4
3
2
1
0

  

3.优先队列

  有些情况下,队列中元素的处理顺序需要根据这些元素的特性来决定,而不只是在队列中创建或插入的顺序。例如,财务部门的打印作业作业可能要优先于一个开发人员打印的代码清单。PriorityQueue使用队列内容的有序顺序来决定获取哪一个元素。

from queue import PriorityQueue
import time
import random
import threading

# 使用heapq实现优先队列
#定义一个可比较对象
class CompareAble:
    def __init__(self,priority,jobname):
        self.priority = priority
        self.jobname = jobname

    def __lt__(self, other):
        if self.priority <= other.priority:
            return False
        else:
            return True

tasks = [(i, "do task %s"%i) for i in range(10,100,5)]
def produce(pq,lock):
    while True:
        lock.acquire()
        task = tasks[random.randint(0,len(tasks)-1)]
        print('put %s %s in pq'%(task[0],task[1]))
        pq.put(CompareAble(task[0],task[1]))
        lock.release()
        time.sleep(1)

def consumer(pq,lock):
    while True:
        lock.acquire()
        try:
            if pq.empty():
                continue
            task = pq.get_nowait()
            if task:
                print(task.priority, task.jobname)
        finally:
            lock.release()
            time.sleep(1)

if __name__ == '__main__':
    task_queue = PriorityQueue()
    task_lock = threading.Lock()
    for i in range(3):
        t = threading.Thread(target=produce,args=(task_queue,task_lock))
        t.setDaemon(False)
        t.start()
    for i in range(2):
        t = threading.Thread(target=consumer,args=(task_queue,task_lock))
        t.setDaemon(False)
        t.start()

  这个例子有很多个线程在处理作业,要根据调用get()时队列中元素的优先级来处理。运行消费者线程是,增加到队列中的元素的处理顺序取决于线程上下文切换。

put 75 do task 75 in pq
put 65 do task 65 in pq
put 30 do task 30 in pq
75 do task 75
65 do task 65
put 25 do task 25 in pq
put 70 do task 70 in pq
put 20 do task 20 in pq
70 do task 70
30 do task 30
put 70 do task 70 in pq
put 80 do task 80 in pq
put 25 do task 25 in pq

  

  

 

posted @ 2020-03-25 15:16  King~~~  阅读(594)  评论(0编辑  收藏  举报