1. 程式人生 > >python併發程式設計之執行緒剩餘內容(執行緒佇列,執行緒池)及協程

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('主程式任務')