欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

生产者、消费者模型---Queue类

程序员文章站 2023-11-02 19:23:46
Queue队列在几乎每种编程语言都会有,python的列表隐藏的一个特点就是一个后进先出(LIFO)队列。而本文所讨论的Queue是python标准库queue中的一个类。它的原理与列表相似,但是先进先出(FIFO)队列。而内部实现更为完善,有很好的数据保护机制和较高的稳定性。 Queue队列在编程 ......

queue队列在几乎每种编程语言都会有,python的列表隐藏的一个特点就是一个后进先出(lifo)队列。而本文所讨论的queue是python标准库queue中的一个类。它的原理与列表相似,但是先进先出(fifo)队列。而内部实现更为完善,有很好的数据保护机制和较高的稳定性。

queue队列在编程中的实际应用:进程中的通信

       假如两个进程需要互通数据,怎么做?用全局变量,然后在进程中通过global关键字引入全局变量?那么问题是,怎么控制时间效应问题,即什么时候获取、传送变量?如何保证数据的安全性?显然这种方案不是很恰当。python为实现进程的通信提出了几种机制,本文的queue就是其中一种。另外还有value,pipe,signal等。

关于signal可以看看我之前写的文章:

python进程间通信--信号signal

 

首先需要介绍queue的类方法:

1. put()          将元素塞进队列,当队列满时不阻塞等待

2. put_nowait()    将元素塞进队列,当队列满时阻塞等待

3. get()           从队列中取出元素,如果队列为空,阻塞等待

4.get_nowait()     从队列中取出元素,如果队列为空,不阻塞等待

5. full()           判断队列是否为已经满

6. empty()        判断队列是否为空

7. qsize()         获取队列的元素个数

8. task_done()     当队列中的任务完成之后会自动调用task_done通知queue,并对join()方法其作用

9. join()          阻塞等待直到所有的队列任务完成(被取出)

 

几个关键方法的详细解析

1. put(item,block = true,timeout = none)

将数据放进队列,item为需要塞进的元素,可以是基本数据类型变量,也可以是函数。block默认为true,即当queue已经满时,阻塞等待(阻塞是同步的,会影响下面的程序运行)。timeout为阻塞等待超时时间,单位为秒,当超过指定时间,退出阻塞,同时报出queue.full错误。

 

2. put_nowait(item)

基本用法与put相同。当队列为满时,不阻塞等待,相当于put(item,block = false)

 

3. get(block= true ,timeout = none)

    获取队列元素,block默认为true,当队列为空时,阻塞等待。timeout为超时时间,单位为秒,当超过指定时间,退出等待。

 

一、queue类方法基本使用(为了方便调用接口,在queue基础上再进行了一次封装):

from queue import queue

class myqueue():             #自定义一个myqueue类
    def __init__(self,size=3):
        self.max_size = size
        self.queue = queue(size)

  #put()方法可以传入数值
    # item1 = 2
    # item2 = 3
    # item3 = 3
    # queue.put(item1)
    # queue.put(item2)
    # queue.put(item3)

    # 超过长度的内容
    # item4 = 5
    # queue.put_nowait(item4)

  #put()方法也可以传入函数
    def _print_num(self,n):
        num = n
        return num

    def write_queue(self):
        for n in range(4):
            try:
              self.queue.put_nowait(self._print_num(n))  #如果队列已经满了,会报出full错误
            except:
                print('队列已经满了,无法添加内容')


    def print_queue_length(self):
       print('队列的长度是:',self.queue.qsize())

    def get_queue(self):
        if self.queue.empty() is false:
            queue_size = self.queue.qsize()
            n = 1
            for i in range(queue_size):
                if n > queue_size:
                    print('队列已经空了')
                value = self.queue.get()
                print('队列第%s个值是:%s'%(n,value))
                n += 1
        else:
          print('队列已经空了')


#实例化代码
myqueue = myqueue()
myqueue.write_queue()
myqueue.print_queue_length()
myqueue.get_queue()

运行结果

生产者、消费者模型---Queue类

 

二、多进程间通信:

from multiprocessing import process,manager

#将数据装进队列
def put_msg(q,lock):
    lock.acquire()
    for i in range(3):
        print('put the %s into the queue'%i)
        q.put(i)
    lock.release()


#将数据取出
def get_msg(q):
    while true:
        if not q.empty():
            value = q.get(false)
            print('get the %s from the queue'%value)
        else:
            break


if __name__ == '__main__':
    manager = manager()
    q = manager.queue(5)    #队列长度设为5
    lock = manager.lock()
    processes = []
    process1 = process(target=put_msg,args=(q,lock))
    process2 = process(target=get_msg,args=(q,))

    processes.append(process1)
    processes.append(process2)
    for p in processes:
        p.start()
        p.join()

在父进程中创建queue,传入两个子进程,因为python中父进程无法与子进程进行通信,必须使用manage来实现。为了只有一个进程在对queue进行操作,使用manage的lock

 

结果:
put the 0 into the queue
put the 1 into the queue
put the 2 into the queue
get the 0 from the queue
get the 1 from the queue
get the 2 from the queue

 

参考文章: