python进程和线程(六)
协程
协程,又称微线程,纤程。英文名Coroutine。顾名思义,协程是协作式的,也就是非抢占式的程序(线程是抢占式的)。协程的关键字是yield,一看到这个就想到了生成器对不对?那就顺便回顾一下生成器的知识点,只要叫什么器的,那肯定就是函数形式,生成器也是函数,只不过多了一个yield在函数中:
def foo():
print('ok')
yield foo()
猜一下foo()执行我的结果是什么?结果是什么都不会打印,为什么呢?打印foo()是什么看一下:
# -*- coding: utf-8 -*- def foo():
print('ok')
yield gen = foo()
print(gen) >>><generator object foo at 0x000001AE31BCA318>
原来foo()是一个生成器函数,只能通过next放方法执行了。
# -*- coding: utf-8 -*- def foo():
print('ok')
yield gen = foo()
# print(gen)
gen.__next__()
>>>ok
这样才能打印出ok来。那除了__next__()方法,我们知道还有两种方法可以执行生成器函数:
deffoo():print('ok')yieldprint('ok2')yield6#yield也可以返回内容,返回的内容给了调用他的那一步,相当于returngen=foo()next(gen)s=gen.__next__()print(s)#next()#只有两个yield,再执行这一步就会报错了>>>ok>>>ok2>>>6
next()
deffoo():print('ok')s=yield6print(s)print('ok2')yieldgen=foo()print(next(gen))gen.send('创给yield的值')#send也可以执行一次生成器,还可以传值给yield>>>ok>>>6>>>创给yield的值>>>ok2
send()
为什么说yield是协程的关键字呢?因为协程是用户态的切换,就是说用户想什么时候切换就什么时候切换(这里的用户就是编程者),而yield刚好可以控制这一点。
协程的两个优点:
优点1: 协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。
优点2: 不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
因为协程是一个线程执行,那怎么利用多核CPU呢?最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。
这里看不懂上面两个优点没关系,看下面的例子就能更好的理解了:
1.yield方式简单实现协程
这里将吃包子的人增加一个,看看yield怎么实现:
import time def customer(name):
print('等包子。。。')
while True:
baozi = yield
print('%s拿到了包子%s'%(name,baozi)) def producer(c1,c2):
c1.__next__()
c2.__next__()
n = 0
while True:
time.sleep(1) #做包子需要一点时间
c1.send(n)
c2.send(n+1)
n += 2 if __name__ == '__main__':
c1 = customer('xiao')
c2 = customer('bai')
producer(c1,c2)
2.Greenlet方式
greenlet是一个用C实现的协程模块,相比与python自带的yield,它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator
from greenlet import greenlet def test1():
print(1111)
gr2.switch()
print(2222)
gr2.switch() def test2():
print(3333)
gr1.switch()
print(4444) gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()
没有安装这个库的话,需要安装一下,然后看打印的结果,是不是可以控制随时切换啦,很神奇。
1111
3333
2222
4444
3.Gevent方式
同样, 没有安装的话需要安装一下
import gevent
import requests,time
start=time.time()
def f(url):
print('GET: %s' % url)
resp =requests.get(url)
data = resp.text
print('%d bytes received from %s.' % (len(data), url)) # f('https://www.python.org/')
# f('https://www.baidu.com/')
# f('https://www.sina.com.cn/')
# f("http://www.xiaohuar.com/hua/") gevent.joinall([
gevent.spawn(f, 'https://www.python.org/'),
gevent.spawn(f, 'https://www.baidu.com/'),
gevent.spawn(f, 'https://www.sina.com.cn/'),
gevent.spawn(f, 'http://www.xiaohuar.com/hua/'),
]) print("cost time:",time.time()-start)
大家可以比较一下使用协程和直接按顺序执行有没有提升效率。
到了这里,协程的基础知识也说完了,还有很多专门开发关于协程的库,因为协程很有作用,这里的例子很简单,但是这里面门道很深的。进程和线程的内容,都是死的,但是协程可以灵活运用,需要不断的去研究创新的。
python进程和线程(六)的更多相关文章
- python 进程和线程(代码知识部分)
二.代码知识部分 一 multiprocessing模块介绍: python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情 ...
- python 进程与线程(理论部分)
一.理论部分 一 什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 举例(单核+多道,实现多个进程的并发执行): egon在一个时间段内有很多任务要做:python备课的 ...
- python 进程和线程
python中的进程.线程(threading.multiprocessing.Queue.subprocess) Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就 ...
- Python进程、线程、协程
进程和线程的解释 进程(process)和线程(thread)是操作系统的基本概念,计算机的核心是CPU,它承担了所有的计算任务: 单个CPU一次只能运行一个任务,代表单个CPU总是运行一个进程,其他 ...
- python进程、线程、协程(转载)
python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资 ...
- Python进程和线程
引入进程和线程的概念及区别 1.线程的基本概念 概念 线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但 ...
- Python进程、线程、协程详解
进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. ...
- python——进程、线程、协程
Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/usr/bin/env pytho ...
- Python进程与线程
进程与线程:*进程: 进程是系统中程序执行和资源分配的基本单元, 每个进程都有自己的数据段(存储数据).代码段(存储代码).堆栈段(对象和变量). # 全局变量等资源在多个进程中不能 ...
随机推荐
- 1. 开篇-springboot环境搭建
最初学习strurs2时,虽然觉得也挺好用的,但也有一些不便的地方:1. 模型绑定必须要在Action中声明对应模型的成员变量:2. Action中对外提供调用的接口必须明确注明:3. 要声明一大堆的 ...
- python插入记录后取得主键id的方法(cursor.lastrowid和conn.insert_id())
#!/usr/bin/python # import MySQL module import MySQLdb # get user input name = raw_input("Pleas ...
- python之@property
在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改: s = Student() s.score = 9999 这显然不合逻辑.为了限制score的 ...
- MySQL使用一张表的字段更新另一张表的字段
转自https://blog.csdn.net/anxpp/article/details/73173274 update table1 t1 left join table2 t2 on t1.ke ...
- java的Junit的用法(转发)
初级https://blog.csdn.net/andycpp/article/details/1327147/ 中级https://blog.csdn.net/andycpp/article/det ...
- 用ASP.NET Core 2.0 建立规范的 REST API -- GET 和 POST
本文所需的一些预备知识可以看这里: http://www.cnblogs.com/cgzl/p/9010978.html 和 http://www.cnblogs.com/cgzl/p/9019314 ...
- C/C++反三角函数使用注意
最近写的东西用到了数学库中的acos函数,但是代码在运行的时候有时候会出莫名其妙的错误,比如返回值是个特别大的数. 最后在debug 的时候发现acos返回的数据很奇怪,但是传入的参数明明没有问题,可 ...
- .NET Core 迁移躺坑记
最近将自己负责的一个核心接口系统从.Net Framework迁移到了.Net Core. 整体过程,从业务层面说一般般吧(整体还好但还是搞的业务有感,没出严重故障)但是技术层面上感觉其实并没有达到要 ...
- 大白话5分钟带你走进人工智能-第十五节L1和L2正则几何解释和Ridge,Lasso,Elastic Net回归
第十五节L1和L2正则几何解释和Ridge,Lasso,Elastic Net回归 上一节中我们讲解了L1和L2正则的概念,知道了L1和L2都会使不重要的维度权重下降得多,重要的维度权重下降得少,引入 ...
- 将本地文件传输到GitHub
统一概念: 工作区:增删文件和内容 暂存区:键入命令 git add 改动的文件,此次改动就放到了 『暂存区』 本地仓库 :键入命令 git commit ,此次改动就放到了『本地仓库』,每个 com ...