day 09 课堂笔记 多进程

1. 进程之间的通信

1.1基于文件方式

  • 需求

    我们要完成一个抢票系统,12306,现在10个人进行查票,这个是并行或者并发的效果,但是买票的过程一定是串行的。我们用代码简单实现。

    进程在内存中原则上来说数据时不能共享的,但是进程可以共享磁盘。所以我们的余额数据应该存入文件中。

    from multiprocessing import Process,Lock
    import json
    import os
    import time
    import random
    
    
    def check():
    
        time.sleep(random.randint(1, 2))
        with open('ticket.json', mode='r', encoding='utf-8') as f1:
            dic = json.load(f1)
            print(f'{os.getpid()}查询了票数,剩余{dic["num"]}票')
            f1.close()
    
    
    def buy():
        with open('ticket.json', mode='r', encoding='utf-8') as f1:
            dic = json.load(f1)
            f1.close()
        if dic['num'] > 0:
            dic['num'] -= 1
            time.sleep(random.randint(1, 2))
            with open('ticket.json', mode='w', encoding='utf-8') as f1:
                json.dump(dic, f1)
                f1.close()
            print(f'{os.getpid()}进程购买成功!')
        else:
            print('票已售完')
    
    def task(lock):
        check()
    
        lock.acquire()
        buy()
        lock.release()
    
    
    if __name__ == '__main__':
        lock = Lock()
        for i in range(10):
            p = Process(target=task,args=(lock,))
            p.start()
    
    

1.2基于队列的方式

1.2.1队列的学习

队列,就是Queue,他是一个容器型的数据类型,这个容器型的数据类型比较特殊,他的原则是先进先出原则。就是因为先进先出的原则,他是不需要我们手动加锁的。他是进程之间最常用的通信方式。

from multiprocessing import Queue

# q = Queue(3)
# 先进先出原则
# q.put('barry')
# q.put('玮哥')
# q.put(666)
#
# print(q.get())
# print(q.get())
# print(q.get())

q = Queue(3)
q.put('barry')
q.put('玮哥')
q.put(666)
# q.put('冲哥')  # 当你插入的数据超过最大值时,队列默认阻塞直到其他进程取值。
# q.put('冲哥',block=False)  # 当你插入的数据超过最大值时,队列默认阻塞直到其他进程取值。

print(q.get())
print(q.get())
print(q.get())
# print(q.get(block=False))
print(q.get(timeout=3))  # 阻塞3秒,3秒过后再无值插入,则报错。

队列其他参数:

  1. 队列里的数量不宜过大。进程之间的通信,就是通知、链接等小数据。(不宜放入视频,图片等)
  2. maxsize = 10000000虽然可以设置无限大,但是队列存在内存中,不宜过大
  3. block = True: 超过上限默认阻塞, block = False , 超过上限直接报错。
  4. timeout: 设置阻塞时间, 超出阻塞时间还处于阻塞状态就会报错。

1.3,基于管道的方式(不推荐使用)

1.3.1创建管道的类

Pipe([duplex]):在进程之间创建一条管道, 并返回元组(conn1, conn2),其中conn1,conn2表示管道两端的连接对象,强调一点:必须在产生Process对象之前产生管道。

1.3.2参数介绍

dumplex:默认管道是全双工的,如果将dumplex设置成False,conn1只能用于接收,conn2只能用于发送。

1.3.3主要方法

conn1.close():关闭连接。如果conn1被垃圾回收,将自动调用此方法

conn1.fileno():返回连接使用的整数文件描述符

conn1.poll([timeout]):如果链接上的数据可用,返回True。timeout指定等待的最长时限。如果省略此参数,方法将立即返回结果。如果将timeout设置成None,操作将无限的等待数据到达。

conn1.recv_bytes([maxlength]):接收c.send_bytes()方法发送的一条完整的字节消息。maxlength指定要接收的最大字节数。如果进入的消息超过了这个最大值,将引发IOError异常,并且在连接上无法进行进一步读取。如果连接的另外一端已经关闭,再也不存在任何数据,将引发EOFError异常。

**conn.send_bytes(buffer[, offset [, size]])😗*通过链接发送字节数据缓冲区,buffer是支持缓冲区接口的任意对象,offset是缓冲区中的字节偏移量,而size是要发送字节数。结果数据以单条消息的形式发出,然后调用c.recv_bytes()函数进行接收。

**conn1.recv_bytes_into(buffer[, offset])😗*接收一条完整的字节消息,并把它保存在buffer对象中,该对象支持可写入的缓冲区接口(即bytearray对象或类似的对象)。offset指定缓冲区中放置消息处的字节位移。返回值是收到的字节数。如果消息长度大于可用的缓冲区空间,将引发BufferTooShort异常。

  • 代码展示

    from multiprocessing import Process,Pipe
    import time,os
    
    
    def consumer(p,name):
        left,right=p
        left.close()
        while True:
            try:
                baozi=right.recv()
                print('%s 收到包子:%s' %(name,baozi))
            except EOFError:
                right.close()
                break
                
    
    def producer(seq,p):
        left,right=p
        right.close()
        for i in seq:
            left.send(i)
            # time.sleep(1)
        else:
            left.close()
    
            
    if __name__ == '__main__':
        left,right=Pipe()
    
        c1=Process(target=consumer,args=((left,right),'c1'))
        c1.start()
    
    
        seq=(i for i in range(10))
        producer(seq,(left,right))
    
        right.close()
        left.close()
    
        c1.join()
        print('主进程')
    

    但是,管道是有问题的,管道会造成数据的不安全,官方给予的解释是管道有可能会造成数据损坏。

2.生产者消费者模型

2.1引子

无论你接触过的模型,设计模型,理论知识,都是用特别高大上的话术给你描述的云里雾里的。核心就是告诉你一种代码的写作方法,套路。

**生产者:**生产数据的一方(进程)就叫做生产者。

**消费者:**接收数据并进行下一步操作就是消费者。

生活中的例子:厨师生产东西,顾客吃东西,这就是生产者,消费者。
我生产出包子,然后怎么给他吃?应该是有一个盆,我把包子放在盆里,然后他从盆里取包子吃,这就是平时咱们见到的例子。假设,没有这个盆了:我生产一个,他吃一个,他吃的过程中,我不会继续生产包子,等他吃完了,我在生产包子,他吃的时候我是不能生产的,我们两个紧紧耦合在一起,这样是不科学的,对吧。厨师就是生产包子,不管你吃不吃完,都是生产包子,然后给盆,消费者跟盆打交道,他不会跟出厨子打交道的。所以:厨师这一类人就是生产包子,然后跟盆打交道,而消费者也是一类人,他们也是直接跟盆打交道。 一个盆解耦了,非常关键的一点,平衡了两者之间的生产力和消费力,存在,生产者就会一直生产,消费者就会一直消费,这个盆作为解耦概念。平时去快餐店吃饭就是这个道理。
消费者起一个进程,生产者起一个进程,盆就是队列。

生产者消费者模型三要素:生产者,消费者,队列

from multiprocessing import Process,Queue
import time
import random


def producer(q):

    for i in range(1,6):
        time.sleep(random.randint(1, 3))
        q.put(f'{i}号包子')
        print(f'生产出了{i}号包子')


def consumer(q):

    while 1:
        res = q.get()
        time.sleep(random.randint(1, 2))
        print(f'消费者吃了{res}')

if __name__ == '__main__':
    q = Queue(5)
    p1 = Process(target=producer,args=(q,))
    p2 = Process(target=consumer,args=(q,))
    p1.start()
    p2.start()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
系统根据B/S,即所谓的电脑浏览器/网络服务器方式,运用Java技术性,挑选MySQL作为后台系统。系统主要包含对客服聊天管理、字典表管理、公告信息管理、金融工具管理、金融工具收藏管理、金融工具银行卡管理、借款管理、理财产品管理、理财产品收藏管理、理财产品银行卡管理、理财银行卡信息管理、银行卡管理、存款管理、银行卡记录管理、取款管理、转账管理、用户管理、员工管理等功能模块。 文中重点介绍了银行管理的专业技术发展背景和发展状况,随后遵照软件传统式研发流程,最先挑选适用思维和语言软件开发平台,依据需求分析报告模块和设计数据库结构,再根据系统功能模块的设计制作系统功能模块图、流程表和E-R图。随后设计架构以及编写代码,并实现系统能模块。最终基本完成系统检测和功能测试。结果显示,该系统能够实现所需要的作用,工作状态没有明显缺陷。 系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。进入银行卡列表,管理员可以进行查看列表、模糊搜索以及相关维护等操作。用户进入系统可以查看公告和模糊搜索公告信息、也可以进行公告维护操作。理财产品管理页面,管理员可以进行查看列表、模糊搜索以及相关维护等操作。产品类型管理页面,此页面提供给管理员的功能有:新增产品类型,修改产品类型,删除产品类型。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值