操作系统——Python:生产者——消费者

标题:Python生产者——消费者模型

本文章的生产者是可以选择多个的,同样消费者也是可以选择多个的,所以中间过程只能用文字叙述,不能用图片来演示(图片需要布局)
先说明,缓冲区最大限制定义了为10,如有个人需要,可以自定义一个entry框输入你的缓冲区容纳最大物品个数,某个状态下只能有一个进程(线程)进行

描述:生产者——消费者模型

在工作中,大家可能会碰到这样一种情况:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、线程、进程等)。产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。在生产者与消费者之间在加个缓冲区,我们形象的称之为仓库,生产者负责往仓库了进商品,而消费者负责从仓库里拿商品,这就构成了生产者消费者模式。结构图如下:
如图

1.生产者模块

class Producer(threading.Thread):    #该类自动继承threading.Thread,
    def run(self):      #所以会自动调用threading.Thread的__init__方法,只需要重写父类的run方法成你想要表达形式就行
        global count    #所以不需要写构造方法(__init__)
        global key      #count是用来记录物品个数的,key是用来互斥信号量,防止该进程执行会同时执行另一个进程两者都定义全局变量
        while True:#循环
            if count<10 and key:   #如果物品未满,并且key为True(可访问)
                key=False          #进入后立即锁住,防止别的进程执行
                t.insert("end","%s is producing 1 product\n" % (self.getName()))#将信息输入到文本框。getName是threading.Thread的方法,可获取进程名字
                count+=1
                t.insert("end","%d products in the queue\n" %(count))
                t.update()
                key=True           #解锁
            time.sleep(random.randrange(5))      #随机阻塞(0-5s)

消费者模块

class Consumer(threading.Thread):    #和生产者一致
    def run(self):
        global count
        global key
        while True:
            if count>0 and key:
                key=False
                t.insert("end","%s is consuming 1 product\n" % (self.getName()))
                count-=1
                t.insert("end","%d products in the queue\n" %(count))
                t.update()
                key=True
            time.sleep(random.randrange(5))

main模块

def main():
    o = eval(e.get())         #e为entry框,可输入一行,e.get()可以读取e输入的内容
    e.delete('0','end')       #读取后删除输入内容
    q = eval(h.get())
    h.delete('0','end')
    for i in range(o):        #o为e输入内容,为生产者个数
        p = Producer()        #初始化
        p.start()             #生产者进程执行,start方法是继承threading.Thread的,会自动调用run方法
    for i in range(q):        #q为h输入内容,为消费者个数
        c = Consumer()        #初始化
        c.start()             #消费者进程执行,start方法是继承threading.Thread的,会自动调用run方法

总的整合

from queue import Queue
from tkinter import *
import random,threading,time
count=0
key =True
mostkey=1
class Producer(threading.Thread):
            def run(self):
                global count
                global key
                global t
                global mostkey
                while True:
                    #global count
                    if count<10 and key:
                        key=False
                        t.insert("end","%s is producing 1 product\n" %(self.getName()))
                        count+=1
                        t.insert("end","%d products in the queue\n" %count)
                        t.update()
                        key=True
                        if mostkey==0:
                            break
                        #self.data.put(count)
                    time.sleep(random.randrange(5))
        
class Consumer(threading.Thread):
            def run(self):
                global count
                global key
                global t
                global mostkey
                while True:
                    #global count
                    if count>0 and key:
                        key=False
                        t.insert("end","%s is consuming 1 product\n" %(self.getName()))
                        count-=1
                        t.insert("end","%d products in the queue\n" %count)
                        t.update()
                        key=True
                        if mostkey==0:
                            break
                    time.sleep(random.randrange(5))
def main():
                global e
                global h
                o = eval(e.get())
                e.delete('0','end')
                q = eval(h.get())
                h.delete('0','end')
                for i in range(o):
                    p = Producer()
                    p.start()#
                for i in range(q):
                    c = Consumer()
                    c.start()
def SKT():#通过让key==True,让进程继续执行,达到类似于继续的效果
                global key
                key=True
def T1():#通过让key==False,让进程无法执行,达到类似于暂停的效果
                global key
                key=False
def DK():#设置mostkey互斥,可以跳出循环,让进程结束
        global mostkey
        mostkey=0
root =Tk()
root.title('生产者——消费者')
root.geometry("500x500")
lab1=Label(root,text="生产者个数",fg="red",bg="white").grid(row=0,column=1)
lab2=Label(root,text="消费者个数",fg="red",bg="white").grid(row=1,column=1)
global e
e = Entry(root, show=None)
global h 
h = Entry(root, show=None)
e.grid(row=0,column=1,columnspan=2)
h.grid(row=1,column=1,columnspan=2)
global t
t = Text(root, height=100)
t.grid(row=2,column=2)
menubar = Menu(root) 
filemenu = Menu(menubar, tearoff=False)
filemenu.add_command(label='开始', command=main)
filemenu.add_command(label='暂停', command=T1)
filemenu.add_command(label='继续', command=SKT)
filemenu.add_command(label='结束', command=DK)
menubar.add_cascade(label='执行操作', menu=filemenu)
root.config(menu=menubar)
root.mainloop()#最好这里写窗口对象.mainloop(),如果套在另一个主窗口
#就可以对对总模块封装成一个def xxx():如果这里是mainloop。那么会一直报错主线程不在主循环里,百度了具体原因还未知,没有有用的信息
#毕竟代码能跑起来就行了,不要管为什么了

效果截图

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值