day 32異步+回調、線程queue、線程Event、協程、單線程下實現遇到IO切換
一、異步+回調:線程是誰空誰調,進程是主進程調用
from concurrent.futures import ProcessPoolExcutor,ThreadPoolExecutor
from threading import current_thread
import requests,os,time,random
def get(url):
print(‘%s GET %s‘%(current_thread().name,url))
response=requests.get(url)
time.sleep(random.randint(1,3))
if response.status_code=200:
return response.text
def pasrse(obj):
res=obj.result()
print(‘%s 解析結果為:%s‘%(current_thread().name,len(res)))
if __name__==‘__main__‘:
urls=[
‘https://www.baidu.com‘,
‘https://www.baidu.com‘,
‘https://www.baidu.com‘,
‘https://www.baidu.com‘,
‘https://www.baidu.com‘,
‘https://www.baidu.com‘,
‘https://www.baidu.com‘,
‘https://www.baidu.com‘,
‘https://www.python.org‘,
]
pool=ThreadPoolExecutor(4)
for url in urls:
obj=pool.submit(get,url)
obj.add_done_callback(pasrse)
print(‘主線程‘,current_thread().name)
二、queue
隊列:先進先出
q.put(1)
q.put(2)
q.put(3)
# q.put(4)
print(q.get())
print(q.get())
print(q.get())
堆棧:後進先出
q.put(‘a‘)
q.put(‘b‘)
q.put(‘c‘)
print(q.get())
print(q.get())
print(q.get())
優先級隊列:可以以小元組的形式往隊列裏存值,第一個元素代表優先級,數字越小優先級越高
q.put((10,‘user1‘))
q.put((-3,‘user2‘))
q.put((-2,‘user3‘))
print(q.get())
print(q.get())
print(q.get())
三、Event
from threading import Event,current_thread,Thread
import time
event=Event()
def check():
print(‘%s 正在檢測服務是否正常....‘ %current_thread().name)
time.sleep(5)
event.set()
def connect():
count=1
while not event.is_set():
if count == 4:
print(‘嘗試的次數過多,請稍後重試‘)
return
print(‘%s 嘗試第%s次連接...‘ %(current_thread().name,count))
event.wait(1)
count+=1
print(‘%s 開始連接...‘ % current_thread().name)
if __name__ == ‘__main__‘:
t1=Thread(target=connect)
t2=Thread(target=connect)
t3=Thread(target=connect)
c1=Thread(target=check)
t1.start()
t2.start()
t3.start()
c1.start()
event.isSet():返回event的狀態值;
event.wait():如果 event.isSet()==False將阻塞線程;
event.set(): 設置event的狀態值為True,所有阻塞池的線程激活進入就緒狀態, 等待操作系統調度;
event.clear():恢復event的狀態值為False。
四、協程
1、單線程下實現並發:協程
並發指的多個任務看起來是同時運行的
並發實現的本質:切換+保存狀態
並發、並行、串行:
並發:看起來是同時運行,切換+保存狀態
並行:真正意義上的同時運行,只有在多cpu的情況下才能
實現並行,4個cpu能夠並行4個任務
串行:一個人完完整整地執行完畢才運行下一個任務
from greenlet import greenlet
import time
def eat(name):
print(‘%s eat 1‘ %name)
time.sleep(30)
g2.switch(‘alex‘)
print(‘%s eat 2‘ %name)
g2.switch()
def play(name):
print(‘%s play 1‘ %name)
g1.switch()
print(‘%s play 2‘ %name)
g1=greenlet(eat)
g2=greenlet(play)
g1.switch(‘egon‘)
day 32異步+回調、線程queue、線程Event、協程、單線程下實現遇到IO切換