本章節主要介紹,使用單執行緒實現併發,即只用乙個主線程(很明顯可利用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
deftest1
(name)
:print
(f' test1 running'
) gevent.sleep(2)
print
(f' test1 stop'
)def
test2
(name)
:print
(f' test2 running'
) gevent.sleep(2)
print
(f' 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
deftest1
(name)
:print
(f' test1 running'
) time.sleep(2)
print
(f' test1 stop'
)def
test2
(name)
:print
(f' test2 running'
) time.sleep(2)
print
(f' 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
deftest1()
:print
(f' test1 running'
) time.sleep(2)
print
(f' test1 stop'
)def
test2()
:print
(f' test2 running'
) time.sleep(2)
print
(f' 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
deftask()
: time.sleep(2)
start = time.time(
)for i in
range(5
):task(
)print
('同步耗時:%0.2fs'
%(time.time(
)- start)
)# 10.2s
deftask()
: time.sleep(2)
asy_time = time.time(
)g_lis =
for i in
range(5
):)gevent.joinall(g_lis)
print
('非同步耗時:%0.2fs'
%(time.time(
)- asy_time)
)# 2s
# gevent模組,開啟乙個乙個任務等待時,則切換下乙個任務,這裡每個任務都遇到,所以同時開啟,同時一起都在執行,所以結果為2s
python 併發程式設計 協程 協程介紹
協程 是單執行緒下的併發,又稱微執行緒,纖程。英文名coroutine。一句話說明什麼是執行緒 協程是一種使用者態的輕量級執行緒,即協程是由使用者程式自己控制排程的 需要強調的是 1.python的執行緒屬於核心級別的,即由作業系統控制排程 如單執行緒遇到io或執行時間過長就會被迫交出cpu執行許可...
併發程式設計 協程
一 協程介紹 協程 是單執行緒下的併發,又稱微執行緒,纖程。英文名coroutine。一句話說明什麼是執行緒 協程是一種使用者態的輕量級執行緒,即協程是由使用者程式自己控制排程的。需要強調的是 對比作業系統控制線程的切換,使用者在單執行緒內控制協程的切換 優點如下 缺點如下 總結 必須在只有乙個單執...
python 併發程式設計 協程 greenlet模組
不敢是yield,還是greenlet都沒有實現檢測io,實現遇到io切換效果 如果我們在單個執行緒內有20個任務,要想實現在多個任務之間切換,使用yield生成器的方式過於麻煩 需要先得到初始化一次的生成器,然後再呼叫send。非常麻煩 而使用greenlet模組可以非常簡單地實現這20個任務直接...