1. 線程的其他方法 2. 線程隊列 線程隊列中三種隊列形式,所使用的方法相同,都有put(),get(),put_nowait(),get_nowait(),qsize(),full(),empty() 等這些方法.就只傳一組先進先出的代碼 import queue 先進先出隊列:queue.Qu ...
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('主程式任務')