Python-訊號量和執行緒池-semaphore ThreadPoll

TigerJin發表於2021-09-09

訊號量

  其實本質上是鎖,Lock是單鎖,訊號量是指定多把鎖,也就是說透過訊號量指定多個數執行緒可以訪問相同資源,一般情況下讀操作可以有多個,但寫操作同時只有一個

 

訊號量模組  semaphore

  # 使用起來和普通鎖沒 什麼區別,但這個是比鎖更加粗粒度鎖,鎖的是執行緒

  # 線上程例項前加鎖,把鎖傳遞進執行緒,線上程結束時候釋放鎖

from threading import Thread, Semaphorefrom queue import Queue  def add(chan, sem_lock):    for i in range(10):        chan.put(i)    # 釋放鎖    sem_lock.release()  if __name__ == '__main__':    numbers = Queue()    # 申明訊號量    sem_lock = Semaphore(4)    sem_lock.acquire()    # 把鎖傳遞進執行緒    tasks = {Thread(target=add, args=(numbers, sem_lock), name="北門吹雪 %s" % i) for i in range(10)}    for task in tasks:        task.start()    for task in tasks:        task.join()    print(numbers.get())

  

執行緒池

  不僅僅是數量控制,可以獲取執行緒狀態、任務狀態、執行緒返回值等資訊

  執行緒池模組  ThreadPollExecutor

 

執行緒池使用過程

  1. 例項化執行緒池

  2. 提交任務,會有個返回物件,submit是不會堵塞,立即返回

  3. 讓主執行緒等待執行緒執行完成

  4. 關閉執行緒池

 

獲取狀態資訊  執行緒物件

  1. 判斷是否執行完        .done()

  2. 獲取任務執行結果,堵塞    .result()

  3. 取消任務            .cancle()

 

對多個執行緒列表獲取結果  執行緒物件

  1. as_complated        獲取已經執行完成的執行緒結果


def add(number, name):    sum = 0    for i in range(number):        sum += i    # 模擬個執行緒執行堵塞情況    time.sleep(random())    # 返回執行緒執行結果    return sum  if __name__ == '__main__':    thread_pool = ThreadPoolExecutor(max_workers=3)    print("北門吹雪:http://www.cnblogs.com/2bjiujiu/")    name = "北門吹雪"    tasks = {thread_pool.submit(add, randint(10, 20), name) for _ in range(20)}     # map方法和as_completed最大區別在於map變化的只是引數執行緒是同一個執行緒,而as_completed可以執行不同的執行緒任務    for data in thread_pool.map(add, {randint(10, 20) for _ in range(20)}):        print(data)

  2. map            直接返回執行緒執行結果,保持傳遞進去順序


def add(number):    sum = 0    for i in range(number):        sum += i    # 模擬個執行緒執行堵塞情況    time.sleep(random())    # 返回執行緒執行結果    return sum  if __name__ == '__main__':    print("北門吹雪")    thread_pool = ThreadPoolExecutor(max_workers=3)    tasks = {thread_pool.submit(add, randint(10, 20)) for _ in range(20)}     # map方法和as_completed最大區別在於map變化的只是引數執行緒是同一個執行緒,而as_completed可以執行不同的執行緒任務    for data in thread_pool.map(add, {randint(10, 20) for _ in range(20)}):        print(data)

  3. wait          等待所有執行緒執行完成


from concurrent.futures import ThreadPoolExecutor, as_completed, waitfrom random import randint, randomimport time  def add(number):    sum = 0    for i in range(number):        sum += i    # 模擬個執行緒執行堵塞情況    time.sleep(random())    # 返回執行緒執行結果    return sum  if __name__ == '__main__':    thread_pool = ThreadPoolExecutor(max_workers=3)    tasks = {thread_pool.submit(add, randint(10, 20)) for _ in range(20)}    print("北門吹雪")    # 主執行緒等待所有子執行緒執行完,不需要結果    # wait(tasks)

1 ='font-family: "Microsoft YaHei"'>北門吹雪:http://www.cnblogs.com/2bjiujiu//span>

經驗:

  1. 執行緒池和訊號量在某種程度如允許執行的執行緒數效果上是一樣,但執行緒池可以獲取執行緒執行結果得到執行緒執行狀態

  2. 使用執行緒池需要首先例項化,然後提交執行緒,返回執行緒物件,然後在主執行緒中選擇獲取結果或者不需要結果,也可以選擇堵塞等待執行緒執行完或不等待執行緒執行完

  3. 獲取執行緒執行結果,可以參照Go語言中CSP通訊模式,個人覺得這是個非常好的解決方案,這樣的執行緒池介面提交遠比CSP通訊來的複雜

1 ='font-family: "Microsoft YaHei"'>北門吹雪:http://www.cnblogs.com/2bjiujiu//span>

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2144/viewspace-2802505/,如需轉載,請註明出處,否則將追究法律責任。

相關文章