在作業系統中程序是資源分配的最小單位, 執行緒是cpu排程的最小單位。
協程:是單執行緒下的併發,又稱微執行緒,纖程。英文名coroutine。一句話說明:協程是一種使用者態的輕量級執行緒,即協程是由使用者程式自己控制排程的。也就是說程式設計師用**來控制切換.
參考:
#程序 啟動多個程序 程序之間是由作業系統負責呼叫
#執行緒 啟動多個執行緒 真正被cpu執行的最小單位實際是執行緒
#開啟乙個執行緒 建立乙個執行緒 暫存器 堆疊
#關閉乙個執行緒#協程
#本質上是乙個執行緒
#能夠在多個任務之間切換來節省一些io時間
#協程中任務之間的切換也消耗時間,但是開銷要遠遠小於程序執行緒之間的切換
#實現併發的手段
import
time
defconsumer():
while
true:
x = yield
time.sleep(1)
print('
處理資料 :
',x)
defproducer():
c =consumer()
next(c)
for i in range(10):
time.sleep(1)
print('
生產資料:
',i)
c.send(i)
#這個生產者消費者模型 模擬了程式的來回切換, 但是不能規避io時間
producer()
使用pip3 install greenlet 和 pip3 install gevent 安裝好模組,繼續:
#真正的協程模組就是使用greenlet完成的切換
from greenlet import
greenlet
defeat():
print('
eating start')
g2.switch()
#切換到g2
print('
eating end')
g2.switch()
defplay():
print('
playing start')
g1.switch()
#切換到g1
print('
playing end')
g1 = greenlet(eat) #
委託給g1
g2 =greenlet(play)
g1.switch()
參考:
#協程是一種使用者態的輕量級執行緒,即協程是由使用者程式自己控制排程的。
import
time
import
gevent
defeat():
print('
eating start')
#time.sleep(1) # gevent 不能感知到time.sleep時間
gevent.sleep(1)
print('
eating end')
defplay():
print('
playing start')
gevent.sleep(1)
print('
playing end')
g1 =gevent.spawn(eat)
g2 =gevent.spawn(play)
g1.join()
g2.join()
gevent的正確方式:
## 匯入這句,將所有模組中的阻塞io都打成乙個包。就可以感知 time.sleep
from gevent import
monkey;monkey.patch_all()
import
time
import
gevent
import
threading
defeat():
print(threading.current_thread().getname()) #
dummy 假的,虛擬的。
(threading.current_thread())
print('
eating start')
time.sleep(1.2)
print('
eating end')
defplay():
(threading.current_thread().getname())
(threading.current_thread())
print('
playing start')
time.sleep(1)
print('
playing end')
g1 = gevent.spawn(eat) #
註冊到協程,遇到io將自動切換
g2 =gevent.spawn(play)
#g1.join()
#g2.join()
gevent.joinall([g1,g2])
print('
master')
#程序和執行緒的任務切換由作業系統完成
#協程任務之間的切換由程式(**)完成,只有遇到協程模組能識別的io操作的時候,程式才會進行任務切換,實現併發的效果
同步和非同步:
#同步 和 非同步
from gevent import
monkey;monkey.patch_all()
import
time
import
gevent
deftask(n):
time.sleep(1)
(n)def
sync():
for i in range(5):
task(i)
defasync():
g_lst =
for i in range(5):
g =gevent.spawn(task,i)
gevent.joinall(g_lst)
#for g in g_lst:g.join()
sync() #同步
async() #
非同步
爬蟲時使用協程併發
#協程 : 能夠在乙個執行緒中實現併發效果的概念
#能夠規避一些任務中的io操作
#在任務的執行過程中,檢測到io就切換到其他任務
#多執行緒 被弱化了
#協程 在乙個執行緒上 提高cpu 的利用率
#協程相比於多執行緒的優勢 切換的效率更快
#爬蟲的例子
#請求過程中的io等待
from gevent import
monkey;monkey.patch_all()
import
gevent
from urllib.request import urlopen #
內建的模組
defget_url(url):
response =urlopen(url)
content = response.read().decode('
utf-8')
return
len(content)
g1 = gevent.spawn(get_url,'
')g2 = gevent.spawn(get_url,'
')g3 = gevent.spawn(get_url,'
')g4 = gevent.spawn(get_url,'
')g5 = gevent.spawn(get_url,'
')gevent.joinall([g1,g2,g3,g4,g5])
(g1.value)
(g2.value)
(g3.value)
(g4.value)
(g5.value)
ret = get_url('
')print(ret)
python 併發程式設計 協程 協程介紹
協程 是單執行緒下的併發,又稱微執行緒,纖程。英文名coroutine。一句話說明什麼是執行緒 協程是一種使用者態的輕量級執行緒,即協程是由使用者程式自己控制排程的 需要強調的是 1.python的執行緒屬於核心級別的,即由作業系統控制排程 如單執行緒遇到io或執行時間過長就會被迫交出cpu執行許可...
Python 併發程式設計(協程)
本章節主要介紹,使用單執行緒實現併發,即只用乙個主線程 很明顯可利用cpu只有乙個 為此我們需要先回顧下併發的本質 切換 儲存狀態 ps 在介紹程序理論時,提及程序的三種執行狀態,而執行緒才是執行單位,所以也可以將上圖理解為執行緒的三種狀態 單執行緒下併發稱為 協程 特點 缺點 gevent 是乙個...
python 併發程式設計 協程 greenlet模組
不敢是yield,還是greenlet都沒有實現檢測io,實現遇到io切換效果 如果我們在單個執行緒內有20個任務,要想實現在多個任務之間切換,使用yield生成器的方式過於麻煩 需要先得到初始化一次的生成器,然後再呼叫send。非常麻煩 而使用greenlet模組可以非常簡單地實現這20個任務直接...