生产者、消费者模型—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() 从队列中取出元素,如果队列为空,不阻塞等待

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

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

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

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

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

几个关键方法的详细解析

  1. put(item,block = True,timeout = None)

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

  1. put_nowait(item)

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

  1. 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

解析:

操作系统中的进程本质上是一个程序在一个数据集上动态执行的过。而进程通常是由程序、数据集和进程控制块组成。

程序:也就是我们平时在IDE上编写的代码,描述了一个进程的内部运行逻辑和功能;

数据集:程序执行过程中需要使用到的资源,包括IO资源和基本数据;

进程控制块:操作系统通过进程控制块来对进程进行控制和管理,记录进程的外部特征和描述进程的执行过程

为了确保进程的独立性和安全性,操作系统在执行程序的时候会用到一种数据解构–栈。程序和数据的入栈和出栈对应进程的等待执行和正式执行。如此一来,各进程间的数据集是相互隔离的(即使可能在同一个栈中)。要进行进程间的通信或者子进程和父进程间的通信,就必须通过一定的机制。上面谈到到的Queue和Manage正是python中实现进程间通信的其中两种。

参考文章:

http://python.jobbole.com/86181/

Original: https://www.cnblogs.com/thomson-fred/p/10018609.html
Author: 2015夏
Title: 生产者、消费者模型—Queue类

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/610714/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Skywalking-08:OAL原理——如何动态生成Class类

    OAL 如何动态生成 Class 类 代码入口 在 org.apache.skywalking.oal.rt.OALRuntime#start 方法 public void sta…

    Java 2023年6月5日
    097
  • No qualifying bean of type ‘org.springframework.transaction.TransactionManager’ available: more than one ‘primary’ bean found among candidates:

    完整的异常提示信息: No qualifying bean of type ‘org.springframework.transaction.TransactionMa…

    Java 2023年5月30日
    0115
  • Java面试必问:ThreadLocal终极篇 淦!

    开场白 张三最近天气很热心情不是很好,所以他决定出去面试跟面试官聊聊天排解一下,结果刚投递简历就有人约了面试。 我丢,什么情况怎么刚投递出去就有人约我面试了?诶。。。真烦啊,哥已经…

    Java 2023年6月9日
    079
  • Docker安装和卸载(centos)

    Docker安装和卸载 一,已安装Docker,卸载Docker 1.方法一 sudo yum remove docker \ docker-client \ docker-cli…

    Java 2023年6月15日
    067
  • zabbix–监控服务端口

    这里实现服务器上面所有的服务端口监控(包括一个服务多端口状况),有异常并进行告警。 zabbix-agent端配置 ✏️ 创建自动发现配置文件 vim /etc/zabbix/za…

    Java 2023年5月30日
    060
  • RabbitMQ——ACK确认机制

    一。介绍 1.消费者从RabbitMQ收到消息并处理完成后,反馈给RabbitMQ,RabbitMQ收到反馈后才将此消息从队列中删除 2.消费者在处理消息出现了网络不稳定、服务器异…

    Java 2023年5月30日
    0108
  • Spring 常见面试题总结 | JavaGuide

    首发于 JavaGuide 在线网站:Spring 常见面试题总结 最近在对 JavaGuide 的内容进行重构完善,同步一下最新更新,希望能够帮助你。 Spring 基础 什么是…

    Java 2023年6月9日
    066
  • 没有二十年功力,写不出Thread.sleep(0)这一行“看似无用”的代码!

    你好呀,我是喜提七天居家隔离的歪歪。 这篇文章要从一个奇怪的注释说起,就是下面这张图: 我们可以不用管具体的代码逻辑,只是单单看这个 for 循环。 在循环里面,专门有个变量 j,…

    Java 2023年6月5日
    068
  • java LinkedList (详解)

    Java 链表(LinkedList) 一、链表简介 1、链表 (Linked List) 是一种常见的基础数据结构,是一种线性表,但是链表不会按线性表的顺序存储数据,而是每个节点…

    Java 2023年6月5日
    0128
  • 封装RabbitTemplate,使用自定义消息转换器

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年6月7日
    064
  • java封装结果集

    java封装结果集 java封装结果集 存在问题 一个用户的操作,比如登录,就可能会有很多种情况,用户层面的:账号错误、密码错误;服务器层面的:数据库错误等等情况。但是我们正常的是…

    Java 2023年6月5日
    071
  • 123取反操作为什么是-124 取反操作

    首先请记住一点,在计算机中所有的二进制都是以补码的形式存储的,所以你最后取反之后只是这个数的补码,你还需要转换成源码,才是我们最终的十进制数字 下面是计算过程: 正数取反(123,…

    Java 2023年6月6日
    0101
  • Java核心技术-泛型、集合

    Day10 泛型程序设计 对于Java泛型的转换需要记住一下几个事实: 虚拟机中没有泛型,只有普通的类和方法 所有的类型参数都会替换为他们的限定类型 会合成桥方法来保持多态 为保持…

    Java 2023年6月5日
    081
  • 十九、网络编程

    十九、🔴网络编程 19.1 网络编程 19.1.1 软件架构 C/S 结构 :全称为 Client/Server 结构,是指客户端和服务器结构。常见程序有 Q…

    Java 2023年6月5日
    077
  • Java 重载

    java允许一个类中含有多个同名方法,但要求各个同名方法的形参数量或类型或顺序不一致。 调用方法时按照传入的实参调用对应的方法,这就叫重载。 如果同名方法且形参一致,那就不叫重载了…

    Java 2023年6月5日
    067
  • 回溯问题学习总结

    回溯问题 三种情况 每种情况都有子集,组合,排列三种题型 无重复元素不可复选 //子集问题 …

    Java 2023年6月8日
    075
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球