day43(协成)
协程(纤程):一个线程的多个部分。
比线程的单位更小。
在一个线程中可以开启很多协程。
在执行当前操作时,遇到I/O操作就会冻结当前操作,去执行其他任务,不断的检测上一个任务是否 -,如果I/O结束了就继续从冻结的地方开始
I/O操作是不占CPU的
协程的特点:
1.冻结当前程序任务的特点
2.可以规避I/O操作的时间
我们今天顺便讲了生成器,(用时间换了空间,每制造出一个资源就消费一个资源)
好的,!下面正式进入正题????
greenlet 切换(在携程这个模块中做多个协程之间的切换的)
from gevent import monkey;monkey.patch_all()
# 它会把下面导入的所有的模块中的IO操作都打成一个包,gevent就能够认识这些IO了
import time
import gevent
# 使用gevent模块来执行多个函数,表示在这些函数遇到IO操作的时候可以在同一个线程中进行切花
# 利用其他任务的IO阻塞时间来切换到其他的任务继续执行
# spawn来发布协程任务
# join负责开启并等待任务执行结束
# gevent本身不认识其他模块中的IO操作,但是如果我们在导入其他模块之前执行from gevent import monkey;monkey.patch_all()
# gevent就能够认识在这句话之后导入的模块中的所有IO操作了
from threading import currentThread
def eat():
print('eating1',currentThread())
time.sleep(1)
print('eating2')
def play():
print('playing1',currentThread())
time.sleep(1)
print('playing2')
g1 = gevent.spawn(eat)
g2 = gevent.spawn(play)
g1.join() # start 且等待g执行完毕
g2.join()
# 休息一会儿
# 协程——tcp 协议的socket并发server
# 异步和同步的测试
from gevent import monkey;monkey.patch_all()
import gevent
import time
def task(i):
time.sleep(0.5)
print(i)
def sync(): # 同步
for i in range(10):
task(i)
def async(): # 异步
#gevent.joinall([gevent.spawn(task, i) for i in range(10)])
g_lst = []
for i in range(10):
g = gevent.spawn(task, i)
g_lst.append(g)
# for g in g_lst:g.join()
gevent.joinall(g_lst)
async()
print('-'*20)
sync()
# 爬取页面的例子
from gevent import monkey;monkey.patch_all()
from urllib.request import urlopen
import gevent
import time
def get_page(url):
res = urlopen(url)
print(len(res.read()))
url_lst = [
'http://www.baidu.com',
'http://www.sogou.com',
'http://www.sohu.com',
'http://www.qq.com',
'http://www.cnblogs.com',
]
start = time.time()
gevent.joinall([gevent.spawn(get_page,url) for url in url_lst])
print(time.time() - start)
start = time.time()
gevent.joinall([gevent.spawn(get_page,url) for url in url_lst])
print(time.time() - start)
start = time.time()
for url in url_lst:get_page(url)
print(time.time() - start)
server端
# from gevent import monkey;monkey.patch_all()
# import socket
# import gevent
# def async_talk(conn):
# try:
# while True:
# conn.send(b'hello')
# ret = conn.recv(1024)
# print(ret)
# finally:
# conn.close()
# sk = socket.socket()
# sk.bind(('127.0.0.1',9000))
# sk.listen()
# while True:
# conn,addr = sk.accept()
# gevent.spawn(async_talk,conn)
# sk.close()
client端
# from gevent import monkey;monkey.patch_all()
# import socket
# import gevent
# from threading import Thread
# def socket_client():
# sk = socket.socket()
# sk.connect(('127.0.0.1',9000))
# while True:
# print(sk.recv(1024))
# sk.send(b'bye')
# sk.close()
# # for i in range(500):
# # Thread(target=socket_client).start()
# gevent.joinall([gevent.spawn(socket_client) for i in range(500)])
# 进程5 线程20 协程500个 —— 通用的组合 —— 50000
# 进程 线程 协程
# 并发编程的设计
# 进程 线程 协程 都用