# 線程中的信號量 # 和進程中的信號量概念一樣,創建好信號量的深度后,同一時間只有n個線程可以訪問被信號量保護的代碼 # 同一時間只有4個線程可以訪問被信號量保護的代碼 # import time # from threading import Semaphore, Thread # # def func(sem, a, b): # sem.acquire() # time.sleep(1) # print(a + b) # sem.release() # # if __name__ == '__main__': # # sem = Semaphore(4) # 創建信號量,4個深度 # for i in range(10): # t = Thread(target=func, args=(sem, i, i + 5)) # t.start() # 線程中的事件 # 和進程中的事件概念一樣 # 事件的狀態 # False狀態 # wait()阻塞 # True狀態 # wait()非阻塞 # 改變事件的狀態 # clear()設置事件狀態為Flase,即使wait()阻塞 # set()設置事件狀態為True,即使wait()非阻塞 # 線程中的事件例子 # 模擬 # 連接數據庫 # 檢測數據庫的可連接情況 # 起兩個線程 # 第一個線程:連接數據庫 # 第一個線程會阻塞等待這個事件,等待一個信號,這個信號來告訴自己和數據庫之間的網絡是通的 # 第二個線程:檢測與數據庫之間的網絡是否是通的 # 模擬延時一會后,將事件的狀態設置為True,使這個事件變為非阻塞,此時第一個線程就會檢測到該事件為非阻塞,則會知道與數據庫之間的網絡是通的 import time import random from threading import Event, Thread def connect_db(e): ''' 模擬檢測數據庫可以連接后,則連接數據庫 :param e: :return: ''' count = 3 while count > 0: #e.wait() # 如果事件e為False,則會阻塞在這里 e.wait(1) # wait可以帶參數,表示如果事件是阻塞的話,這里最長會阻塞1S中 if e.is_set() == True: # 檢測下事件是否為非阻塞,因為到這里可能是wait阻塞超時導致(這種事件狀態還是為False阻塞),也可能確實是檢測網絡的線程發的解除阻塞信號 print('連接數據庫') break else: print('連接數據庫超時') count -= 1 else: print('連接數據庫到了上限次還沒有連接數據庫成功') raise TimeoutError # 主動拋出一個超時異常 def check_web(e): ''' 檢測數據庫可連接情況,模擬延時一會后,將事件設置為True,變為非阻塞,表示網絡是通的 :param e: 事件 :return: ''' time.sleep(random.randint(0, 5)) e.set() if __name__ == '__main__': e = Event() # 事件創建好后,默認是False阻塞的 t = Thread(target=connect_db, args=(e, )) t2 = Thread(target=check_web, args=(e, )) t.start() t2.start() t.join() t2.join()