python进阶9——Joinablequeue和协程

并发模式

JoinableQueue

创建可连接的共享进程队列,它们也是队列,但是这队列比较特殊.它可以允许消费者通知生产者项目已经被成功处理。这里必须是生产者生产完了,进程被挂起,等到消费者完成消费的时候,生产者进程就结束,然后主程序结束。将消费者进程设置为守护进程。这样的话,主进程结束的时候,消费进程也就结束了。
JoinableQueue较于Queue(这里的Queue是multprocessing的,不是queue的),有两个新的方法:
1,q.task_done()
使用者使用此方法发出信号,表示q.get()返回的项目已经被处理。如果调用此方法的次数大于从队列中删除的项目数量,将引发ValueError异常。
2,q.join()
生产者将使用此方法进行阻塞,直到队列中所有项目均被处理。阻塞将持续到为队列中的每个项目均调用q.task_done()方法为止。

from multiprocessing import Process, JoinableQueue
import time

def producer(queue):#生产者函数
    for i in range(5):
        item = f'Item {i}'
        queue.put(item)
        print(f'Producer: Put {item} into the queue')
        time.sleep(1)
    # 告知消费者任务已完成
    queue.join()

def consumer(queue):#消费者函数
    while True:
        item = queue.get()
        print(f'Consumer: Got {item} from the queue')
        queue.task_done()

if __name__ == '__main__':
    # 创建 JoinableQueue 对象
    queue = JoinableQueue()

    # 创建生产者进程
    producer_process = Process(target=producer, args=(queue,))
    producer_process.start()#启动生产者进程

    # 创建消费者进程
    consumer_process = Process(target=consumer, args=(queue,))
    consumer_process.start()#启动消费者进程

    # 等待生产者进程完成
    producer_process.join()

    # 等待消费者进程完成
    queue.join()
    consumer_process.terminate()

在这里插入图片描述

注意这种方法是通过生产者来“得知”进程情况的,整个生产消费流程的终结,在消费者调用q.task_done()时,会触发一次q.join()的检查(q.join()是用来阻塞进程的,最后一个任务完成后,q.task_done()->q.join()->阻塞解除),之后生产者进程退出。
消费者呢?业务逻辑层面上是没有显式的退出的。本例中通过设置为守护进程的方式进行退出。但如果后续主进程还有其他任务,而没有退出呢?那么这些子进程统统沦为僵尸进程,虽然这样对系统资源消耗少(消费者的queue.get()也是阻塞的,所以不会执行循环,仅仅会“卡”在那里,但也不会自动消亡)。我还是倾向于用”生产者queue.put(None) ,消费者见到None则break(退出循环)”的传统方式 进行消费者进程触发退出。但是如果采用这种方式那么JoinableQueue相比Queue就没有优势了。

协程

协程是一种轻量级的并发编程方式,通过使用特定的关键字和语法,可以在单个线程中实现多个协作式任务的并发执行。

在Python中,协程是使用async和await关键字定义的特殊函数。定义协程函数时,需要在函数定义前加上async关键字,表示该函数是一个协程函数。在协程函数内部,可以使用await关键字来暂停协程的执行,等待另一个协程或异步操作完成后再继续执行。
下面的示例中greet函数是一个协程函数,它接受一个名称作为参数,并打印问候语。在打印问候语后,await asyncio.sleep(1)语句将协程暂停1秒钟,模拟一个耗时的操作。然后,协程继续执行,打印告别语。asyncio.get_event_loop()函数手动创建了事件循环。然后,我们使用run_until_complete()方法来运行main()协程直到完成。最后,我们使用close()方法关闭事件循环。

import asyncio

async def greet(name):
    print("\033[91mHello\033[0m", name)
    await asyncio.sleep(1)
    print("\033[92mGoodbye\033[0m", name)

async def main():
    await asyncio.gather(
        greet("Alice"),
        greet("Bob")
    )

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值