进程、线程、协程嵌套出现内层程序丢失
作者:互联网
进程、线程、协程嵌套出现内层程序丢失
复现
import time
import gevent
from gevent import monkey, spawn;
monkey.patch_all()
from concurrent.futures import ThreadPoolExecutor
def func1_gevent():
time.sleep(5)
print('gevent1')
def func2_gevent():
time.sleep(3)
print('gevent2')
def func_thread(gevent_list):
time.sleep(5)
feature_gevent = spawn(func1_gevent)
gevent_list.append(feature_gevent)
func2_gev = spawn(func2_gevent)
gevent_list.append(func2_gev)
def main():
gevent_list = list()
pool = ThreadPoolExecutor(20)
for i in range(10):
pool.submit(func_thread, gevent_list)
print(len(gevent_list))
gevent.joinall(gevent_list)
print(len(gevent_list))
pool.shutdown(wait=True)
print('asdfasdfasdf')
if __name__ == '__main__':
main()
## 运行结果
#0
#0
#asdfasdfasdf
原因
此时,线程池中的线程都submit了,但是线程并未开始执行,停留在time.sleep
==> 在gevent.joinall()
时,gevent_list
中并没有append
任何协程对象,它的length
为0,导致监听程序认为所有协程都已执行完成
==> pool.shutdown(wait=True)
表示等待线程池中的所有线程中的 主程序 都执行结束,再向下执行主进程。这里会等time.sleep
结束,并执行append结束,它并不会判断gevent
是否已经结束
==> 在执行print('asdfasdfasdf')
主进程的时候,可能之前的 gevent
并没有全部执行结束
==> 等待所有线程执行结束,开始执行主进程(即print('asdfasdfasdf')
),然后退出主进程,此时的gevent
可能刚开始执行,导致部分gevent
程序丢失
解决方案
先执行pool.shutdown
,再执行gevent.joinall
。
- 先等待线程中的主程序执行完,此时所有的
gevent
都已经append
到gevent_list
; - 然后开始
joinall
,此时gevent_list
已包含所有需执行或正在执行的gevent
,所以主进程会等所有gevent
结束
def main():
gevent_list = list()
pool = ThreadPoolExecutor(20)
for i in range(10):
pool.submit(func_thread, gevent_list)
# print(len(gevent_list))
# gevent.joinall(gevent_list)
# print(len(gevent_list))
# pool.shutdown(wait=True)
print(len(gevent_list))
pool.shutdown(wait=True)
print(len(gevent_list))
gevent.joinall(gevent_list)
print('asdfasdfasdf')
# 修改后运行结果
#0
#20
#gevent2
#gevent2
#gevent2
#gevent2
#gevent2
#gevent2
#gevent2
#gevent2
#gevent2
#gevent2
#gevent1
#gevent1
#gevent1
#gevent1
#gevent1
#gevent1
#gevent1
#gevent1
#gevent1
#gevent1
#asdfasdfasdf
标签:协程,gevent1,gevent2,list,嵌套,gevent,线程,print 来源: https://www.cnblogs.com/linagcheng/p/16075905.html