linux编程-协程与生产者消费者

本文探讨了Python中使用协程进行并发编程的方法,对比了多线程和多进程,介绍了如何利用生成器和第三方库如greenlet及gevent实现协程并发,同时提供了生产者消费者模式的实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

协程

1.通常在Python中我们进行并发编程一般都是使用多线程或者多进程来实现的,对于计算型任务由于GIL的存在我们通常使用多进程来实现,而对与IO型任务我们可以通过线程调度来让线程在执行IO任务时让出GIL,从而实现表面上的并发。

2.其实对于IO型任务我们还有一种选择就是协程,协程是运行在单线程当中的“并发”,协程相比多线程一大优势就是省去了多线程之间的切换开销,获得了更大的运行效率。Python中的asyncio也是基于协程来进行实现的。在进入asyncio之前我们先来了解一下Python中怎么通过生成器进行协程来实现并发

下来我们完成一个简单的协程
import time
def A():
    while True:
        print("-----A-----")
        yield
        time.sleep(0.5)
def B(c):
    while True:
        print("-------B-----")
        next(c)
        time.sleep(0.5)
if __name__=="__main__":
    a=A()
    B(a)

这是我们用生成器写的协程能模拟出并发的效果,用一个主进程去运行函数,利用生成器yield很好的演示了并发的效果。处了用生成器外,还可以用一个库,实现协程的并发。这个库就是 greenlet 这个库是python的第三方库,需要安装。
下来看代码:

from greenlet import *
import time 
def A():
    while True:
        print("------a-----")
        gr2.switch()
        time.sleep(0.5)
def B():
    while True:
        print("------b------")
        gr1.switch()
        time.sleep(0.5)
gr1=greenlet(A)
gr2=greenlet(B)
gr1.switch()

这个模块开始创建了两个对象gr1和gr2,先让gr1运行A函数里面的代码打印出a线程跳转运行b函数打印出b线程跳转,以此来实现并发的效果。除了这些还有一个并发网络库 gevent 下来我给大家做个示范。

import sys
import gevent
import time
from gevent import socket,monkey
monkey.patch_all()
def handle_request(conn):
    while True:
        data=conn.recv(1024)
        if not data:
            conn.close():
            break
        print("recv",data)
        conn.send(data)
def server(port):
    s=socket.socket()
    s.bind(("",port))
    s.listen(5)
    while True:
        cli,addr=s.accept()
        gevent.spawn(handle_request,cli)
if __name__=="__main__":
    server(7788)

生产者消费者

import threading
import time
from queue import Queue
class Producer(threading.Thread):
    def run(self):
        global queue
        count = 0
        while True:
            if queue.qsize() < 1000:
                for i in range(100):
                    count = count +1
                    msg = '生成产品'+str(count)
                    queue.put(msg)
                    print(msg)
            time.sleep(0.5)
class Consumer(threading.Thread):
    def run(self):
        global queue
        while True:
            if queue.qsize() > 100:
                for i in range(3):
                    msg = self.name + '消费了 '+queue.get()
                    print(msg)
            time.sleep(1)
if __name__ == '__main__':
    queue = Queue()
    for i in range(500):
        queue.put('初始产品'+str(i))
    for i in range(2):
        p = Producer()
        p.start()
    for i in range(5):
        c = Consumer()
        c.start()

我用类写继承了threading.Thread,重写了父类里面的run方法,这样可以以解决耦合的问题,使代码更加灵活。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值