进程,线程,协程
python多进程:
环境:Ubuntu,python3
python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程。Python提供了非常好用的多进程包multiprocessing。
multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似。
multiprocessing模块的功能众多:支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。
生产者消费者实例:
ps:多进程之间无法直接通信,它必须借助一个第三方的桥梁 __队列(queue)__管道(pipe,Semaphore)
queue::
from multiprocessing import Process
import random
import time
import multiprocessing
def produce(name,q):
while True:
for i in range(5):
item = random.randint(1,5)
q.put(item)#将产品放入队列中
print("生产者",name,"生产了",str(item))
def consume(name,q):
while True:
for i in range(5):
item = q.get()#从队列中取出产品
print("消费者",name,"消费了",item)
if __name__ == '__main__':
q = multiprocessing.Queue(maxsize = 5)
Process(target=produce, args=(1,q)).start()
Process(target=consume, args=(2,q)).start()
#Process创建进程
#target一般是一个可调用对象,比如函数,类
# args传入参数
Semaphore::
from multiprocessing import Process
import random
import time
import multiprocessing
def produce(name,e,q):
while True:
for i in range(5):
e.acquire()#获取信号量,没信号量可用时,将进行阻塞
item = random.randint(1,5)
q.send(item)
print("生产者",name,"生产了",str(item))
def consume(name,e,q):
while True:
for i in range(5):
item = q.recv()
print("消费者",name,"消费了",item)
e.release()#释放信号量
if __name__ == '__main__':
con1, con2 = multiprocessing.Pipe()
#创建两个对象,进行通信
e = multiprocessing.Semaphore(5)
#acquire代表5个可用资源-1。
#release表示现有可用资源+1
Process(target=produce, args=(1,e,con1)).start()
Process(target=consume, args=(2,e,con2)).start()
python多线程:
环境:win10,python3
import random, threading
import queue
#生产者线程
class Producer(threading.Thread):
def __init__(self, name, queue):
threading.Thread.__init__(self, name=name)
self.queue = queue
def run(self):
for i in range(10):
print("%s 生产了 %d \n" % (self.getName(), i))
# 消费者线程
class Consumer(threading.Thread):
def __init__(self, name, queue):
threading.Thread.__init__(self, name=name)
self.queue = queue
def run(self):
for i in range(10):
print("%s 消费了 %d " % (self.getName(), val))
q = queue.Queue(maxsize = 5)
if __name__ == '__main__':
producer = Producer('生产者A', q)
consumer = Consumer('消费者B', q)
producer.start()
consumer.start()
协程:
环境:win10,python3
协程能保留上一次调用时的状态,每次协程重入时,就相当于进入上一次调用的状态。
从yield说起
一个带有 yield 的函数就是一个 generator(生成器),它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就返回一个迭代值,下次执行时从 yield 的下一个语句继续执行,返回当前的迭代值。
yiled和return区别:yield返回执行结果并不中断程序执行,return在返回执行结果的同时中断程序执行。
可以看看:廖雪峰老师的生成器:https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/00138681965108490cb4c13182e472f8d87830f13be6e88000
如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高,注意yield不但可以返回一个值,它还可以接收调用者发出的参数
def consumer():
print('启动生成器\n') # 只有第一次会执行(启动生成器), 之后再调用生成器就会从yield处执行
while True:
n = yield # Python的yield不但可以返回一个值,它还可以接收调用者发出的参数
print('接受到产品%s...'%n)
print('消费产品 %s...\n' % n)
def produce(c):
#c.send(None)
next(c)
#通过c.send(None)或者next(c)启动生成器函数,并执行到第一个yield语句结束的位置
print('开始生产产品...')
n = 0
while n
n = n + 1
print('生成产品 %s...' % n)
print('打包发送产品 %s...' % n)
r = c.send(n) # # 获取生成器consumer中由yield语句返回的下一个值
c.close()
if __name__ == '__main__':
c = consumer() #创建生成器
print('创建生成器')
produce(c)
源码地址:https://github.com/plusyou13/product/tree/master
领取专属 10元无门槛券
私享最新 技术干货