本章节主要介绍,使用单线程实现并发,即只用一个主线程(很明显可利用CPU只有一个),为此我们需要先回顾下并发的本质:切换+保存状态
ps:在介绍进程理论时,提及进程的三种执行状态,而线程才是执行单位,所以也可以将上图理解为线程的三种状态
单线程下并发称为:协程
特点:
缺点:
Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在Python内我们使用这个模块,可以让我们的程序运行,达到一个协程的效果
使用方式:
import gevent
g1 = gevent.spawn(func,args,kwargs)
g1 = gevent.spawn(func,args,kwargs)
g1.join() # 等待g1结束
g2.join() # 等待g2结束
# 或者二合一 gevent.joinall([g1,g2])
g1.value # 拿到g1执行func的返回值
遇到IO自动切换任务
import gevent
def test1(name):
print(f'{name} test1 running')
gevent.sleep(2)
print(f'{name} test1 stop')
def test2(name):
print(f'{name} test2 running')
gevent.sleep(2)
print(f'{name} test2 stop')
g1 = gevent.spawn(test1,'jack')
g2 = gevent.spawn(test2,'tom')
gevent.joinall([g1,g2]) # 注意,我们如果不等待任务运行结束,那么遇到阻塞则不会继续运行了
执行结果:
'''
jack test1 running
tom test2 running
jack test1 stop
tom test2 stop
'''
其中gevent.sleep(2)
是gevent模块可以识别的IO阻塞
而time.sleep(2) 或其它阻塞
是gevent模块所不能识别的,所以我们需在文件的开头增加(代码程序运行前)一个方法,来解决这个问题
from gevent import monkey;monkey.patch_all()
# 上面写法等同于:
# from gevent import monkey
# monkey.patch_all()
import gevent
import time
def test1(name):
print(f'{name} test1 running')
time.sleep(2)
print(f'{name} test1 stop')
def test2(name):
print(f'{name} test2 running')
time.sleep(2)
print(f'{name} test2 stop')
g1 = gevent.spawn(test1,'jack')
g2 = gevent.spawn(test2,'tom')
gevent.joinall([g1,g2]) # 注意,我们如果不等待任务运行结束,那么遇到阻塞则不会继续运行了
执行结果
'''
jack test1 running
tom test2 running
jack test1 stop
tom test2 stop
'''
我们可以使用threading.current_thread().getName()
来查看它们是由谁来执行的
from gevent import monkey;monkey.patch_all()
import gevent
import time
from threading import current_thread
def test1():
print(f'{current_thread().getName()} test1 running')
time.sleep(2)
print(f'{current_thread().getName()} test1 stop')
def test2():
print(f'{current_thread().getName()} test2 running')
time.sleep(2)
print(f'{current_thread().getName()} test2 stop')
g1 = gevent.spawn(test1)
g2 = gevent.spawn(test2)
gevent.joinall([g1,g2])
执行结果
'''
DummyThread-1 test1 running
DummyThread-2 test2 running
DummyThread-1 test1 stop
DummyThread-2 test2 stop
'''
结果为:DummyThread,表示假线程
单线程下,遇到IO时,演示同步与异步的效果
from gevent import monkey;monkey.patch_all()
import gevent
import time
def task():
time.sleep(2)
start = time.time()
for i in range(5):
task()
print('同步耗时:%0.2fs' % (time.time() - start)) # 10.2s
def task():
time.sleep(2)
asy_time = time.time()
g_lis = []
for i in range(5):
g_lis.append(gevent.spawn(task))
gevent.joinall(g_lis)
print('异步耗时:%0.2fs' % (time.time() - asy_time)) # 2s
# gevent模块,开启一个一个任务等待时,则切换下一个任务,这里每个任务都遇到,所以同时开启,同时一起都在运行,所以结果为2s
技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请
点赞 收藏+关注
子夜期待您的关注,谢谢支持!