协程:能够在一个线程中实现并发效果的概念
能够规避一些任务中的IO操作
在任务的执行过程中,检测到IO就切换到其他任务
多线程被弱化了
协程在一个线程上,提高CPU利用率
协程相比多线程有事,切换的效率更快
实现并发的手段
进程——启动多个进程,进程之间由操作系统负责调用
线程——启动多个线程,真正被CPU执行的最小单位实际是线程
开启一个线程,创建一个线程 寄存器 堆栈
协程
本质上是一个线程
能够在多个任务之间切换来节省一些IO时间
协程中任务之间的切换也消耗时间,但是开销远远小于进程线程之间的切换
协程示例
# 进程和线程的任务切换由操作系统完成 # 协程任务之间的切换由程序(代码)完成, # 之后遇到协程模块能识别的IO操作的时候,程序才会进行任务切换,实现并发的效果 from gevent import monkey;monkey.patch_all() # 将他下面引入的包的所有阻塞操作都放入这个包中 import gevent import time def eat(): print('start eating') time.sleep(1) print('end eating') def play(): print('start playing') time.sleep(1) print('end playing') g1 = gevent.spawn(eat) g2 = gevent.spawn(play) g1.join() g2.join()协程
协程的同步和异步
from gevent import monkey;monkey.patch_all() import time import gevent def task(): time.sleep(1) print(12345) def sync(): # 同步 for i in range(10): task() def async(): # 异步 g_lst = [] for i in range(20): g = gevent.spawn(task) g_lst.append(g) gevent.joinall(g_lst) # [g.join for g in g_lst] sync() # 同步 async() # 异步同步异步
爬虫示例
from gevent import monkey monkey.patch_all() import gevent import requests def get_url(url): response = requests.get(url) content = response.content return len(content) print(get_url('http://www.baidu.com')) g1 = gevent.spawn(get_url,'http://www.baidu.com') g2 = gevent.spawn(get_url,'http://www.hao123.com') g3 = gevent.spawn(get_url,'http://www.sogou.com') g4 = gevent.spawn(get_url,'http://www.cnblogs.com') g5 = gevent.spawn(get_url,'http://www.tianmao.com') gevent.joinall([g1,g2,g3,g4,g5]) print(g1.value) print(g2.value) print(g3.value) print(g4.value) print(g5.value)爬虫示例
socket server 示例
from gevent import monkey;monkey.patch_all() import socket import gevent def tack(conn): conn.send(b'hello') print(conn.recv(1024).decode('utf-8')) conn.close() sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen(0) while True: conn,addr = sk.accept() gevent.spawn(tack,conn) sk.close()server
import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) print(sk.recv(1024).decode('utf-8')) info = input('>>>').encode('utf-8') sk.send(info) sk.close()client