Python之路【第十七篇】:Python并发编程|协程
一、协程
协程,又叫微线程,纤程。英文名Coroutine。协程本质上就是一个线程
优点1:协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越来越明显。(简单来说没有切换的消耗)
优点2:不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好,所以执行效率比多线程高很多。(没有锁的概念)
因为协程是一个线程执行,那怎么利用多核CPU呢?最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。
二、yield的简单实现
#_*_ coding:utf-8 _*_
# Author:Simon
# Datetime:2019/9/2 21:07
# Software:PyCharm import time
import queue def consumer(name):
print("--->ready to eat baozi...")
while True:
new_baozi = yield
print("[%s] is eating baozi %s" % (name,new_baozi))
#time.sleep(1) def producer(): r = con.__next__()
r = con2.__next__()
n = 0
while 1:
time.sleep(1)
print("\033[32;1m[producer]\033[0m is making baozi %s and %s" %(n,n+1) )
con.send(n)
con2.send(n+1) n +=2 if __name__ == '__main__':
con = consumer("c1")
con2 = consumer("c2")
p = producer()
三、Greenlet模块
greenlet是一个用C实现的协程模块,相比与python自带的yield,它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator
#_*_ coding:utf-8 _*_
# Author:Simon
# Datetime:2019/9/2 21:29
# Software:PyCharm
from greenlet import greenlet def test1():
print(12)
gr2.switch()
print(34)
gr2.switch()
def test2():
print(56)
gr1.switch()
print(78) gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()
四、Gevent模块
本质就是封装了greenlet模块,它能检测I/O并且遇到I/O自动切换到另外一个任务执行;可以帮我们提升效率
#_*_ coding:utf-8 _*_
# Author:Simon
# Datetime:2019/9/2 21:39
# Software:PyCharm 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)) gevent.joinall([ gevent.spawn(f, 'https://www.jd.org/'),
gevent.spawn(f, 'https://www.xiaohua.com/'),
gevent.spawn(f, 'https://www.baidu.com/'),
gevent.spawn(f, 'https://www.taobao.com/'), ]) # f('https://www.jd.org/')
# f('https://www.xiaohua.com/')
# f('https://baidu.com/')
# f('https://www.taobao.com/')
#
# print("cost time:",time.time()-start)
gevent异步提交任务
from gevent import monkey;monkey.patch_all()
import gevent
import time def eat(name):
print('%s eat 1' % name)
time.sleep(3)
print('%s eat 2' % name) def play(name):
print('%s play 1' % name)
time.sleep(4)
print('%s play 2' % name) g1=gevent.spawn(eat,'simon')
g2=gevent.spawn(play,'zhuzhu') # time.sleep(5) # g1.join()
# g2.join() gevent.joinall([g1,g2]) #相当于上边两行代码 打印:
simon eat 1
zhuzhu play 1
simon eat 2
zhuzhu play 2
基于gevent模块实现并发的套接字通信
单线程、多任务的I/O操作。
#基于gevent实现
from gevent import monkey,spawn;monkey.patch_all()
from socket import * def communicate(conn):
while True:
try:
data=conn.recv(1024)
if not data:break
conn.send(data.upper())
except ConnectionResetError:
break
conn.close() def server(ip,port):
server = socket(AF_INET, SOCK_STREAM)
server.bind((ip,port))
server.listen(5) while True:
conn, addr = server.accept()
spawn(communicate,conn) #造一个协程对象,提交完这个对象它不会执行
server.close() if __name__ == '__main__':
g=spawn(server,'127.0.0.1',8090)
g.join()
##客户端 from socket import *
from threading import Thread,currentThread def client():
client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8090)) while True:
client.send(('%s hello' %currentThread().getName()).encode('utf-8'))
data=client.recv(1024)
print(data.decode('utf-8'))
client.close()
if __name__ == '__main__':
for i in range(500):
t=Thread(target=client)
t.start()
Python之路【第十七篇】:Python并发编程|协程的更多相关文章
- python 并发编程 协程 目录
python 并发编程 协程 协程介绍 python 并发编程 协程 greenlet模块 python 并发编程 协程 gevent模块 python 并发编程 基于gevent模块实现并发的套接字 ...
- 并发编程协程(Coroutine)之Gevent
并发编程协程之Gevent Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporate r ...
- 并发编程 - 协程 - 1.协程概念/2.greenlet模块/3.gevent模块/4.gevent实现并发的套接字通信
1.协程并发:切+保存状态单线程下实现并发:协程 切+ 保存状态 yield 遇到io切,提高效率 遇到计算切,并没有提高效率 检测单线程下 IO行为 io阻塞 切 相当于骗操作系统 一直处于计算协程 ...
- Python并发编程协程(Coroutine)之Gevent
Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporate routine的缩写,直接翻译 ...
- Python之并发编程-协程
目录 一.介绍 二. yield.greenlet.gevent介绍 1.yield 2.greenlet 3.gevent 一.介绍 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutin ...
- python并发编程&协程
0x01 前导 如何基于单线程来实现并发? 即只用一个主线程(可利用的cpu只有一个)情况下实现并发: 并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去执行其他的任务(切换由操 ...
- python 并发编程 协程 gevent模块
一 gevent模块 gevent应用场景: 单线程下,多个任务,io密集型程序 安装 pip3 install gevent Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步 ...
- python 并发编程 协程 协程介绍
协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的 需要强调的是: 1. python的线程属于内 ...
- 【python之路36】进程、线程、协程相关
线程详细用法请参考:http://www.cnblogs.com/sunshuhai/articles/6618894.html 一.初始多线程 通过下面两个例子的运行效率,可以得知多线程的速度比单线 ...
随机推荐
- 压缩、解压命令——gzip、gunzip、tar、zip、bzip2
1.gzip命令与gunzip命令(压缩解压文件): (1)gzip——压缩: 利用touch命令创建一个文件,并向里面写入内容: 对创建的文件进行压缩: (2)解压缩gzip -d或gunzip: ...
- 【DP】【期望】$P1850$换教室
链接 题目描述 有 \(2n\) 节课程安排在$ n$ 个时间段上.在第 \(i\)(\(1 \leq i \leq n\))个时间段上,两节内容相同的课程同时在不同的地点进行,其中,牛牛预先被安排在 ...
- 修改git log中的Date格式
默认的git log查看日志显示的格式如下: Date: Thu Aug 16 17:44:32 2018 +0800 说实话,真不太喜欢这种日期格式还是换成数值比较舒服一点.git bash中使 ...
- JavaScript sort函数
默认排序法则: 按照String类型ASCII码大小排序 如果要倒序排序,我们可以把大的数放前面: var arr = [10, 20, 1, 2]; arr.sort(function (x, y) ...
- 使用charles对jmeter进行抓包
- 你向 Mysql 数据库插入 100w 条数据用了多久?
阅读本文大概需要 2 分钟. ▌目录 多线程插入(单表) 多线程插入(多表) 预处理 SQL 多值插入 SQL 事务( N 条提交一次) ▌多线程插入(单表) 问:为何对同一个表的插入多线程会比单线程 ...
- SpringMVC实现文件下载的两种方式及多文件下载
1.传统方法 @RequestMapping("/download") public String download( String fileName ,String filePa ...
- Systemd笔记
Systemd管理的启动脚本位于 /usr/lib/systemd/system/ 下 Systemd启动顺序约定为: 当前服务满足启动条件, 则立即创建进程进行并行启动, 启动条件指服务的依赖关系( ...
- CentOS7 增加回环地址
添加回环地址的命令和说明如下: #添加一个回环地址到lo网卡,添加多个可以改lo:后边的序号 [要添加的地址] netmask 255.255.255.255 broadcast [要添加的地址] # ...
- 解决docx4j 变量替换 由于变量存在样式式或空白字符 导致替换失败问题
参考文章:https://blog.csdn.net/qq_35598240/article/details/84439929 使用docx4j进行变量替换时 变量(形如:${变量})必须是无格式的, ...