python併發程式設計之執行緒剩餘內容(執行緒佇列,執行緒池)及協程
1. 執行緒的其他方法
import threading
import time
from threading import Thread,current_thread
def f1(n):
time.sleep(1)
print('子執行緒名稱', current_thread().getName()) # 獲取執行緒名
print('%s號執行緒任務'%n)
if __name__ == '__main__':
t1 = Thread(target=f1,args=(1,))
t1.start()
print('主執行緒名稱',current_thread().getName()) # 獲取執行緒名
print('主執行緒ID',current_thread().ident) # 獲取執行緒id
print(current_thread()) # 當前執行緒物件
print(threading.enumerate()) # 當前正在執行的執行緒物件的一個列表 [<_MainThread(MainThread, started 6708)>, <Thread(Thread-1, started 7848)>]
print(threading.active_count()) # 當前正在執行的執行緒數
2. 執行緒佇列
執行緒佇列中三種佇列形式,所使用的方法相同,都有put(),get(),put_nowait(),get_nowait(),qsize(),full(),empty() 等這些方法.就只傳一組先進先出的程式碼
import queue
先進先出佇列:queue.Queue(n)
q = queue.Queue(3)
q.put(1)
q.put(2)
print('當前佇列內容長度',q.qsize())
q.put(3)
print('檢視佇列是否滿了',q.full())
try:
q.put_nowait(4)
except Exception:
print ('佇列滿了')
print(q.get())
print(q.get())
print(q.get())
print('檢視佇列是否為空',q.empty())
try:
q.get_nowait()
except Exception:
print('佇列空了')
先進後出 / 後進先出佇列:queue.LifoQueue(n)
優先順序佇列:
queue.priorityQueue(n)
優先順序佇列中如果第一個引數相同,後面的比較方法為下面的描述.
如果說值裡面的元素是數字型別,那麼當兩個值的優先順序相同時,比較的是兩個值的大小,小的優先被取出來.如果元素是字串,那麼依次比較每個字母的ascii表中的位置,小的優
先被取出來.如果put的資料是一個元組,元組的第一個引數是優先順序數字,數字越小優先順序越高,越先被get到被取出來,第二個引數是put進去的值,如果說優先順序相同,那麼值別忘了應
該是相同的資料型別,字典不行
3. 執行緒池
from concurrent_futures import ThreadPoolExecutor,ProcessPoolExecutor
p = ThreadPoolExecutor(4) #預設的執行緒個數是cpu個數 * 5
p = ProcessPoolExecutor(4) #預設的程序個數是cpu個數
map(f1,可迭代物件) : 非同步提交任務
sublim(f1,引數) : 非同步提交任務,和get方法一樣,如果沒有結果,會等待,阻塞程式
shutdown() : 鎖定執行緒池,等待執行緒池中所有已經提交的任務全部執行完畢 , 相當於close + join
import time
from threading import current_thread
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
def f1(n,s):
time.sleep(1)
# print('%s號子執行緒'%current_thread().ident)
# print(n,s)
return
if __name__ == '__main__':
tp = ThreadPoolExecutor(4)
# tp = ProcessPoolExecutor(4)
# tp.map(f1,range(10)) #非同步提交任務,引數同樣是任務名稱,可迭代物件
res_list = []
for i in range(10):
res = tp.submit(f1,i,'baobao') #submit是給執行緒池非同步提交任務,
print(res)
# res.result()
res_list.append(res)
for r in res_list:
print(r.result())
tp.shutdown() #主執行緒等待所有提交給執行緒池的任務,全部執行完畢 close + join
# for r in res_list:
# print(r.result())
print('主執行緒結束')
執行緒池回撥函式
執行緒池的回撥函式與程序池的相似
import time from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor def f1(n,s): return n*s def f2(n): print('回撥函式',n.result()) if __name__ == '__main__': tp = ThreadPoolExecutor(4) res = tp.submit(f1,11,12).add_done_callback(f2)
4. 協程
生成器版
import time
def f1():
for i in range(10):
time.sleep(0.5)
print('f1=>',i)
yield
def f2():
g = f1()
for i in range(10,20):
time.sleep(0.5)
print('f2=>', i)
next(g)
f1()
f2()
greenlet模組
import time
from greenlet import greenlet
def f1():
print('第一次f1')
g2.switch() #切換到g2這個物件的任務去執行
time.sleep(1)
print('第二次f1')
g2.switch()
def f2():
print('第一次f2')
g1.switch()
time.sleep(1)
print('第二次f2')
g1 = greenlet(f1) #例項化一個greenlet物件,並將任務名稱作為引數參進去
g2 = greenlet(f2)
g1.switch() #執行g1物件裡面的任務
gevent模組
from gevent import monkey;monkey.patch_all()
這個模組只要有io的地方就會自動切換,不必非要用gevent模組,下面的程式碼中gevent.sleep(1) 換成time.sleep(1)也可以執行.
import gevent
from gevent import monkey;monkey.patch_all()
import time
import threading
def f1():
print('第一次f1')
gevent.sleep(1) # time.sleep(1)
print('第二次f1')
def f2():
print('第一次f2')
gevent.sleep(1) #time.sleep(1)
print('第二次f2')
g1 = gevent.spawn(f1) #非同步提交了f1任務
g2 = gevent.spawn(f2) #非同步提交了f2任務
gevent.joinall([g1,g2]) #相當於g1.join()+g2.join()
print('主程式任務')