Python 線程障礙對象 Barrier(轉)

原文:https://www.codersrc.com/archives/6581.html

作者:猿說編程

Python 線程 Barrier 俗稱障礙對象,也稱柵欄,也叫屏障。​

一.Python 線程障礙對象 Barrier 簡介

'''
參數介紹:
    parties — 線程計數器,記錄線程數量,也稱線程障礙數量;
    action — 是一個可調用函數,當等待的線程到達了線程障礙數量parties,其中一個線程會首先調用action 對應函數,之後再執行線程自己內部的代碼;
    timeout — 默認的超時時間;
''' 
# 障礙對象barrier 
barrier = threading.Barrier(parties, action=None, timeout=None)

二.Python 線程障礙對象 Barrier 原理

      與之前介紹 互斥鎖 Lock / 事件 Event / 定時器 Timer 等不同,多線程 Barrier 會設置一個線程障礙數量 parties ,如果等待的線程數量沒有達到障礙數量 parties ,所有線程會處於阻塞狀態,當等待的線程到達了這個數量就會喚醒所有的等待線程。

      可能說的有點抽象,以播放器爲例子:首先一個線程做播放器初始化工作(加載本地文件或者獲取播放地址),然後一個線程獲取視頻畫面,一個線程獲取視頻聲音,只有當初始化工作完畢,視頻畫面獲取完畢,視頻聲音獲取完畢,播放器纔會開始播放,其中任意一個線程沒有完成,播放器會處於阻塞狀態直到三個任務都完成!

三.Python 線程障礙對象 Barrier 函數介紹

      wait(timeout=None)  — 阻塞並嘗試通過障礙,如果等待的線程數量大於或者等於線程障礙數量 parties ,則表示障礙通過,執行 action 對應函數並執行線程內部代碼,反之則繼續等待;

      如果 wait(timeout=None)  等待超時,障礙將進入斷開狀態!如果在線程等待期間障礙斷開或重置,此方法會引發 BrokenBarrierError 錯誤,注意添加異常處理,演示代碼查看案例一;

      reset — 重置線程障礙數量,返回默認的空狀態,即當前阻塞的線程重新來過,如果在線程等待期間障礙斷開或重置,此方法會引發 BrokenBarrierError 錯誤,注意添加異常處理,演示代碼查看案例二;

四.Python 線程障礙對象 Barrier 使用

1.案例一:常規使用

# 導入線程模塊
import threading
def plyer_display():
    print('初始化通過完成,音視頻同步完成,可以開始播放....')
# 設置3個障礙對象
barrier = threading.Barrier(3, action=plyer_display, timeout=None)
def player_init(statu):
    print(statu)
    try:
        # 設置超時時間,如果2秒內,沒有達到障礙線程數量,
        # 會進入斷開狀態,引發BrokenBarrierError錯誤
        barrier.wait(2)
    except Exception as e: # 斷開狀態,引發BrokenBarrierError錯誤
        print("等待超時了... ")
    else:
        print("xxxooooxxxxxooooxxxoooo")
if __name__ == '__main__':
    statu_list = ["init ready","video ready","audio ready"]
    thread_list = list()
    for i in range(0,3):
        t = threading.Thread(target=player_init,args=(statu_list[i],))
        t.start()
        thread_list.append(t)
    for t in thread_list:
        t.join()

輸出結果:

init ready
video ready
audio ready
初始化通過完成,音視頻同步完成,可以開始播放....
xxxooooxxxxxooooxxxoooo
xxxooooxxxxxooooxxxoooo
xxxooooxxxxxooooxxxoooo

      注意:如果 barrier.wait(timeout=None) 等待超時,會進入斷開狀態,引發 BrokenBarrierError 錯誤,爲了程序的健壯性,最好加上異常處理;

2.案例二:重置線程障礙數量 reset

# 導入線程模塊
import threading
def plyer_display():
    print('初始化通過完成,音視頻同步完成,可以開始播放....')
# 設置3個障礙對象
barrier = threading.Barrier(3, action=plyer_display, timeout=None)
def player_init(statu):
    while True:
        print(statu)
        try:
            # 設置超時時間,如果2秒內,沒有達到障礙線程數量,
            # 會進入斷開狀態,引發BrokenBarrierError錯誤
            barrier.wait(2)
        except Exception as e: # 斷開狀態,引發BrokenBarrierError錯誤
            # print("斷開狀態... ")
            continue
        else:
            print("xxxooyyyxxxooyyyxxxooyyy")
            break
if __name__ == '__main__':
    statu_list = ["init ready","video ready","audio ready"]
    thread_list = list()
    for i in range(0,3):
        t = threading.Thread(target=player_init,args=(statu_list[i],))
        t.start()
        thread_list.append(t)
        if i == 1: # 重置狀態
            print("不想看愛情片,我要看愛情動作片....")
            barrier.reset()
    for t in thread_list:
        t.join()

輸出結果:

init ready
video ready
不想看愛情片,我要看愛情動作片....
init ready
video ready
audio ready
初始化通過完成,音視頻同步完成,可以開始播放....
xxxooyyyxxxooyyyxxxooyyy
xxxooyyyxxxooyyyxxxooyyy
xxxooyyyxxxooyyyxxxooyyy

      注意:如果 barrier.wait(timeout=None) 等待超時,會進入斷開狀態,引發 BrokenBarrierError 錯誤,爲了程序的健壯性,最好加上異常處理;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章