進程:qq要以一個整體的形式暴露給操作系統管理,裡面包含對各種資源的調用,記憶體的對各種資源管理的集合,就可稱之為進程。 線程:是操作系統最小的調度單位,是一串指令的集合。 進程:要操作CPU,必須要先創建一個線程,進程不能單獨執行,進程執行是調動線程,至少要有一個線程; 進程是資源的集合,線程是最小 ...
進程:qq要以一個整體的形式暴露給操作系統管理,裡面包含對各種資源的調用,記憶體的對各種資源管理的集合,就可稱之為進程。
線程:是操作系統最小的調度單位,是一串指令的集合。
進程:要操作CPU,必須要先創建一個線程,進程不能單獨執行,進程執行是調動線程,至少要有一個線程;
進程是資源的集合,線程是最小的單位,所有速度沒有可比性。啟動線程快。
線程共用記憶體空間,進程的記憶體是相互獨立的。
同一個進程的線程之間可以直接交流,兩個進程想通信,必須通過一個中間代理來實現。
創建新線程很簡單,創建新進程需要對其父進程進行一次克隆。
一個線程可以控制和操作同一進程里的其他線程,但是進程只能操作子進程。
使用函數定義一個線程:
import threading,time
def func(num):
print("Runing on %s threading......" %num)
time.sleep(2)
if __name__ == "__main__":
start_time = time.time()
t1 = threading.Thread(target=func,args=(1,)) #生成一個線程t1實例
t2 = threading.Thread(target=func,args=(2,))
t1.start() #啟動線程t1
t2.start()
print(t1.getName()) #獲取線程名
print(t2.getName())
end_time = time.time()
spend_time = end_time - start_time
print("花費時間:",spend_time)
上面代碼,生成了一個線程,線程同時執行,如果正常情況下,肯定先執行t1,然後執行t2,花費的時間是4秒以上,但是使用線程,執行之間只有兩秒多,如下:
Runing on 1 threading...... Thread-1 Thread-2 花費時間: 0.0005929470062255859 Runing on 2 threading......
由於上述代碼是並行的,線程先執行,執行完成之後等待兩秒。
使用類創建線程:
import threading,time class MyThreading(threading.Thread): '''自己創建的類,繼承的是線程的類,覆蓋了之前的類,因此要重寫父類''' def __init__(self,num): super(MyThreading,self).__init__() #括弧裡面是加入參數的 '''重寫父類''' self.num = num def run(self): #定義每個函數運行的函數,類的所有方法在run中,調用run,必須是run函數 print("Running task %s" %self.num) time.sleep(2) if __name__ == "__main__": t3 = MyThreading(1) #定義線程1 t4 = MyThreading(2) t3.start() #執行線程1 t4.start() print(t3.getName()) #獲取線程1的名字 print(t4.getName())
上面代碼,是運用類創建的線程,super(MyThreading,self).__init__(),重寫類,生成新的類,使用類創建線程,所有的方法必須定義在run()函數中。
舊式類啟用線程:
import threading,time
class MyThread(threading.Thread):
'''用舊式類生成線程'''
def __init__(self,num):
threading.Thread.__init__(self)
self.num = num
def run(self):
print("Start the %s threading......" %self.num)
time.sleep(2)
if __name__ == "__main__":
start_time = time.time() #程式執行起始時間
t5 = MyThread(1) #生成線程1實例
t6 = MyThread(2)
t5.start() #啟動線程1
t6.start()
print(t5.getName()) #獲取線程1名字
print(t6.getName()) #獲取線程2名字
end_time = time.time() #程式執行結束時間
spend_time = end_time - start_time #程式執行花費時間
print(spend_time)
代碼運行結果如下:
Start the 1 threading......
Start the 2 threading......
Thread-1
Thread-2
0.0004968643188476562
上面使用舊式類寫的類,啟動線程。
上面的花費時間,是啟用線程的時間,並不是程式執行的時間。上面的代碼是並行運行的。
把線程編程串列執行,即一個線程執行完畢再繼續執行下一個線程,如下:
import threading,time class MyThread(threading.Thread): '''用舊式類生成線程''' def __init__(self,num): threading.Thread.__init__(self) self.num = num def run(self): print("Start the %s threading......" %self.num) time.sleep(2) if __name__ == "__main__": start_time = time.time() # 程式執行起始時間 for i in range(5): t8 = MyThread(i) #生成線程1實例 t8.start() t8.join() #等待線程執行結果,這個線程沒有執行完畢,程式不執行下一步,讓線程執行變成並行 end_time = time.time() #程式執行結束時間 spend_time = end_time - start_time #程式執行花費時間 print("--------all theads has finished----------------") print(spend_time)
運行結果如下:
Start the 0 threading......
Start the 1 threading......
Start the 2 threading......
Start the 3 threading......
Start the 4 threading......
--------all theads has finished----------------
10.011518001556396
從結果可以看出,上面程式執行編程了串列,等待上一個線程執行完畢之後,才會執行下一個線程,只是在裡面加入一個執行,t1.join(),用來讓程式等待。
下麵我們讓兩個線程等待執行的時間不一定,如下:
import threading,time
class MyThread(threading.Thread):
'''用舊式類生成線程'''
def __init__(self,num,execute_time):
threading.Thread.__init__(self)
self.num = num
self.execute_time = execute_time
def run(self):
print("Start the %s threading......" %self.num)
time.sleep(self.execute_time)
print("Threading %s task done!" %self.num)
if __name__ == "__main__":
start_time = time.time() # 程式執行起始時間
t1 = MyThread(1,2) #生成線程1實例
t2 = MyThread(2,4)
t1.start() #執行t1
t2.start() #執行t2
t1.join() #等待線程執行結果,這個線程沒有執行完畢,程式不執行下一步,讓線程執行變成並行
end_time = time.time() #程式執行結束時間
spend_time = end_time - start_time #程式執行花費時間
print("--------all theads has finished----------------")
print(spend_time)
程式執行如下:
Start the 1 threading......
Start the 2 threading......
Threading 1 task done!
--------all theads has finished----------------
2.0026450157165527
Threading 2 task done!
上面程式中,線程t1和t2同時執行,但是t1.join()只等待第一個線程執行完畢,不會等待第二個線程執行完畢再往下執行,可以看出,程式向下執行完畢之後,t2還在等待執行過程中。
主線程問題,程式運行是有一個主線程在運行的。下麵看一個實例:
import threading,time class MyThread(threading.Thread): '''用舊式類生成線程''' def __init__(self,num): threading.Thread.__init__(self) self.num = num def run(self): print("Start the %s threading......" %self.num) time.sleep(4) print("Threaing %s task done!!!!" %self.num) if __name__ == "__main__": start_time = time.time() # 程式執行起始時間 t_objs = [] #創建一個臨時列表,先讓線程都啟動 for i in range(50): t8 = MyThread(i) #生成線程1實例 t8.start() t_objs.append(t8) #啟動所有線程並添加列表中 #print(t_objs) print("當前活躍的線程個數:",threading.active_count()) for t in t_objs: t8.join() #所有線程啟動執行完畢之後,等待所有線程執行完畢之後執行下一個線程 end_time = time.time() #程式執行結束時間 print("--------all theads has finished----------------",threading.current_thread(),threading.active_count()) spend_time = end_time - start_time #程式執行花費時間 print(spend_time)
運行結果如下:
Start the 0 threading......
Start the 1 threading......
Start the 2 threading......
Start the 3 threading......
Start the 4 threading......
Start the 5 threading......
Start the 6 threading......
Start the 7 threading......
Start the 8 threading......
Start the 9 threading......
Start the 10 threading......
Start the 11 threading......
Start the 12 threading......
Start the 13 threading......
Start the 14 threading......
Start the 15 threading......
Start the 16 threading......
Start the 17 threading......
Start the 18 threading......
Start the 19 threading......
Start the 20 threading......
Start the 21 threading......
Start the 22 threading......
Start the 23 threading......
Start the 24 threading......
Start the 25 threading......
Start the 26 threading......
Start the 27 threading......
Start the 28 threading......
Start the 29 threading......
Start the 30 threading......
Start the 31 threading......
Start the 32 threading......
Start the 33 threading......
Start the 34 threading......
Start the 35 threading......
Start the 36 threading......
Start the 37 threading......
Start the 38 threading......
Start the 39 threading......
Start the 40 threading......
Start the 41 threading......
Start the 42 threading......
Start the 43 threading......
Start the 44 threading......
Start the 45 threading......
Start the 46 threading......
Start the 47 threading......
Start the 48 threading......
當前活躍的線程個數: 51
Start the 49 threading......
Threaing 1 task done!!!!
Threaing 6 task done!!!!
Threaing 4 task done!!!!
Threaing 3 task done!!!!
Threaing 2 task done!!!!
Threaing 5 task done!!!!
Threaing 0 task done!!!!
Threaing 9 task done!!!!
Threaing 10 task done!!!!
Threaing 11 task done!!!!
Threaing 7 task done!!!!
Threaing 8 task done!!!!
Threaing 13 task done!!!!
Threaing 12 task done!!!!
Threaing 18 task done!!!!
Threaing 39 task done!!!!
Threaing 15 task done!!!!
Threaing 20 task done!!!!
Threaing 24 task done!!!!
Threaing 26 task done!!!!
Threaing 28 task done!!!!
Threaing 35 task done!!!!
Threaing 22 task done!!!!
Threaing 34 task done!!!!
Threaing 42 task done!!!!
Threaing 21 task done!!!!
Threaing 19 task done!!!!
Threaing 25 task done!!!!
Threaing 27 task done!!!!
Threaing 36 task done!!!!
Threaing 38 task done!!!!
Threaing 43 task done!!!!
Threaing 17 task done!!!!
Threaing 14 task done!!!!
Threaing 33 task done!!!!
Threaing 30 task done!!!!
Threaing 40 task done!!!!
Threaing 44 task done!!!!
Threaing 29 task done!!!!
Threaing 41 task done!!!!
Threaing 16 task done!!!!
Threaing 23 task done!!!!
Threaing 31 task done!!!!
Threaing 32 task done!!!!
Threaing 37 task done!!!!
Threaing 47 task done!!!!
Threaing 46 task done!!!!
Threaing 45 task done!!!!
Threaing 48 task done!!!!
Threaing 49 task done!!!!
--------all theads has finished---------------- <_MainThread(MainThread, started 139803255105280)> 1
4.0112504959106445
上面程式中,我們啟動了50個線程,但是可以看出,其實是由51個線程在執行,其中一個是線程本身,作為主線程,線程執行完畢之後,只剩下主線程,其他線程都被殺死,要先實現並行執行線程,所有線程同時啟動,並等待上一個線程執行完畢,接著執行下一個線程,要藉助列表,先生成一個空的列表,把所有生成的線程添加到列表中,然後再遍歷列表,依次執行啟動的線程。
join()等待所有的線程執行完畢,主線程才繼續執行。
設置守護線程:
正常情況下小,如果沒有設置join(),程式會一直執行,不會管線程是否執行完畢,但是在主線程執行完畢之後,還是會等待其他線程執行完畢,如下:
import threading,time class MyThread(threading.Thread): '''用舊式類生成線程''' def __init__(self,num): threading.Thread.__init__(self) self.num = num def run(self): print("Start the %s threading......" %self.num) time.sleep(4) print("Threaing %s task done!!!!" %self.num) if __name__ == "__main__": start_time = time.time() # 程式執行起始時間 t_objs = [] #創建一個臨時列表,先讓線程都啟動 for i in range(5): t8 = MyThread(i) #生成線程1實例 # t8.setDaemon(True) #把當前線程設置為守護線程 ,必須在start之前 '''程式會等待主線程執行完畢,守護線程執行完畢與否是不管的''' t8.start() t_objs.append(t8) #啟動所有線程並添加列表中 #print(t_objs) print("當前活躍的線程個數:",threading.active_count()) # for t in t_objs: # t8.join() #所有線程啟動執行完畢之後,等待所有線程執行完畢之後執行下一個線程 end_time = time.time() #程式執行結束時間 print("--------all theads has finished----------------",threading.current_thread(),threading.active_count()) spend_time = end_time - start_time #程式執行花費時間 print(spend_time)
運行結果如下:
Start the 0 threading......
Start the 1 threading......
Start the 2 threading......
Start the 3 threading......
Start the 4 threading......
當前活躍的線程個數: 6
--------all theads has finished---------------- <_MainThread(MainThread, started 139642438694656)> 6
0.0012087821960449219
Threaing 1 task done!!!!
Threaing 4 task done!!!!
Threaing 2 task done!!!!
Threaing 0 task done!!!!
Threaing 3 task done!!!
從上面代碼運行結果可以看出,主線程執行完畢之後,又執行了其他線程,程式在執行過程中,啟動了線程,但是不會在意線程是否執行完畢,沒有執行完畢就繼續執行,但是最後會等待其他線程執行完畢之後結束程式。如何讓主線程執行完畢之後,不等待其他線程是否執行完畢就結束線程呢?這裡就要用到守護線程了,如下:
import threading,time class MyThread(threading.Thread): '''用舊式類生成線程''' def __init__(self,num): threading.Thread.__init__(self) self.num = num def run(self): print("Start the %s threading......" %self.num) time.sleep(4) print("Threaing %s task done!!!!" %self.num) if __name__ == "__main__": start_time = time.time() # 程式執行起始時間 t_objs = [] #創建一個臨時列表,先讓線程都啟動 for i in range(5): t8 = MyThread(i) #生成線程1實例 t8.setDaemon(True) #把當前線程設置為守護線程 ,必須在start之前 '''程式會等待主線程執行完畢,守護線程執行完畢與否是不管的''' t8.start() t_objs.append(t8) #啟動所有線程並添加列表中 #print(t_objs) print("當前活躍的線程個數:",threading.active_count()) # for t in t_objs: # t8.join() #所有線程啟動執行完畢之後,等待所有線程執行完畢之後執行下一個線程 end_time = time.time() #程式執行結束時間 print("--------all theads has finished----------------",threading.current_thread(),threading.active_count()) spend_time = end_time - start_time #程式執行花費時間 print(spend_time)
運行結果如下:
Start the 0 threading......
Start the 1 threading......
Start the 2 threading......
Start the 3 threading......
Start the 4 threading......
當前活躍的線程個數: 6
--------all theads has finished---------------- <_MainThread(MainThread, started 140133686212352)> 6
0.0010912418365478516
上面程式把所有其他線程都設置成為了守護線程,t8.setDaemon(),設置守護線程,設置守護線程必須在start()線程開始之前設置,設置完畢之後,從結果可以看出,主線程執行完畢之後,就結束了程式,不會管其他線程是否執行完畢。
全局解釋器鎖
Python GIL(Global Interpreter Lock)
In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)
上面的核心意思就是,無論你啟多少個線程,你有多少個cpu, Python在執行的時候會淡定的在同一時刻只允許一個線程運行,擦。。。,那這還叫什麼多線程呀?莫如此早的下結結論,聽我現場講。
首先需要明確的一點是GIL
並不是Python的特性,它是在實現Python解析器(CPython)時所引入的一個概念。就好比C++是一套語言(語法)標準,但是可以用不同的編譯器來編譯成可執行代碼。有名的編譯器例如GCC,INTEL C++,Visual C++等。Python也一樣,同樣一段代碼可以通過CPython,PyPy,Psyco等不同的Python執行環境來執行。像其中的JPython就沒有GIL。然而因為CPython是大部分環境下預設的Python執行環境。所以在很多人的概念里CPython就是Python,也就想當然的把GIL
歸結為Python語言的缺陷。所以這裡要先明確一點:GIL並不是Python的特性,Python完全可以不依賴於GIL。
python的線程是調用操作系統的原生線程,Python調用C語言的原生介面。
線程鎖(互斥鎖Mutex)
一個進程下可以啟動多個線程,多個線程共用父進程的記憶體空間,也就意味著每個線程可以訪問同一份數據,此時,如果2個線程同時要修改同一份數據,會出現什麼狀況?
import time import threading def addNum(): global num # 在每個線程中都獲取這個全局變數 print('--get num:', num) time.sleep(1) num += 1 # 對此公共變數進行-1操作 num = 0 # 設定一個共用變數 thread_list = [] for i in range(50): t = threading.Thread(target=addNum) t.start() thread_list.append(t) time.sleep(1.000001) # for t in thread_list: # 等待所有線程執行完畢 # t.join() print('final num:', num)
運行程式如下:
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
final num: 49
上面代碼,執行結果有時候是50,有時候是49,如何解決呢?
用戶加鎖,用戶加鎖確保同一時間只有一個線程在修改數據,上面的代碼,如果在規定時間內,沒有執行完畢,那麼將釋放GIL,讓其他線程執行,造成過多修改同一數據,因此要用戶自己加鎖,確保同一時間只有一個線程修改數據。
import time import threading def addNum(): global num # 在每個線程中都獲取這個全局變數 print('--get num:', num) lock.acquire() #獲取一把鎖 time.sleep(1) #在所裡面sleep()會把程式編程串列 num += 1 # 對此公共變數進行-1操作 lock.release() num = 0 # 設定一個共用變數 thread_list = [] lock = threading.Lock() for i in range(10): t = threading.Thread(target=addNum) t.start() thread_list.append(t) for t in thread_list: # 等待所有線程執行完畢 t.join() print('final num:', num)
加鎖,首先聲明一把鎖,lock=threading.Thread(target=addNum),生成一把鎖,然後在函數中加鎖,lock.acquire(),加鎖,lock.release(),最後釋放鎖,把加的鎖進行釋放,為什麼要加鎖呢?因為線程執行的時候,是有實現限制的,在規定時間如果為執行完畢,GIF會釋放,加鎖是為了讓在同一時間內,只有同一個線程執行程式。
加鎖版本
import time import threading def addNum(): global num # 在每個線程中都獲取這個全局變數 print('--get num:', num) time.sleep(1) lock.acquire() # 修改數據前加鎖 num -= 1 # 對此公共變數進行-1操作 lock.release() # 修改後釋放 num = 100 # 設定一個共用變數 thread_list = [] lock = threading.Lock() # 生成全局鎖 for i in range(100): t = threading.Thread(target=addNum) t.start() thread_list.append(t) for t in thread_list: # 等待所有線程執行完畢 t.join() print('final num:', num)
遞歸鎖(嵌套鎖)----RLock(遞歸鎖)
說白了就是在一個大鎖中還要再包含子鎖
下麵來看一個實例:
import threading, time def run1(): print("grab the first part data") lock.acquire() global num num += 1 lock.release() return num def run2(): print("grab the second part data") lock.acquire() global num2 num2 += 1 lock.release() return num2 def run3(): lock.acquire() #第一道鎖加鎖,首先進入此鎖 res = run1() #進入第二道鎖,第二道也有鎖 print('--------between run1 and run2-----') res2 = run2() #平行進入第二道鎖,和上面run1是並行鎖 lock.release() print(res, res2) if __name__ == '__main__': num, num2 = 0, 0 lock = threading.Lock() for i in range(10): t = threading.Thread(target=run3) t.start() while threading.active_count() != 1: print(threading.active_count()) else: print('----all threads done---') print(num, num2)
上面代碼是一把大鎖裡面嵌套一把小鎖,這樣會造成什麼問題呢?如下:
11 11 11 11 11 11 ......
上面代碼執行陷入了一個死迴圈,程式不停的執行,為什麼呢?
遞歸鎖--RLock:防止鎖死
import threading, time def run1(): print("grab the first part data") lock.acquire() global num num += 1 lock.release() return num def run2(): print("grab the second part data") lock.acquire() global num2 num2 += 1 lock.release() return num2 def run3(): lock.acquire() #第一道鎖加鎖,首先進入此鎖 res = run1() #進入第二道鎖,第二道也有鎖 print('--------between run1 and run2-----') res2 = run2() #平行進入第二道鎖,和上面run1是並行鎖 lock.release() print(res, res2) if __name__ == '__main__': num, num2 = 0, 0 lock = threading.RLock() for i in range(10): t = threading.Thread(target=run3) t.start() while threading.active_count() != 1: print(threading.active_count()) else: print('----all threads done---') print(num, num2)
運行結果如下:
grab the first part data
--------between run1 and run2-----
grab the second part data
1 1
grab the first part data
--------between run1 and run2-----
grab the second part data
2 2
grab the first part data
--------between run1 and run2-----
grab the second part data
3 3
grab the first part data
--------between run1 and run2-----
grab the second part data
4 4
grab the first part data
--------between run1 and run2-----
grab the second part data
5 5
grab the first part data
--------between run1 and run2-----
grab the second part data
6 6
grab the first part data
--------between run1 and run2-----
grab the second part data
7 7
grab the first part data
--------between run1 and run2-----
grab the second part data
8 8
grab the first part data
--------between run1 and run2-----
grab the second part data
9 9
grab the first part data
2
--------between run1 and run2-----
grab the second part data
10 10
----all threads done---
10 10
從上面代碼可以看出,使用RLokc()遞歸所能夠正確的執行退出。所以加鎖多次的時候,為了防止鎖死,應該使用遞歸鎖。
Semaphore(信號量)
互斥鎖 同時只允許一個線程更改數據,而Semaphore是同時允許一定數量的線程更改數據 ,比如廁所有3個坑,那最多只允許3個人上廁所,後面的人只能等裡面有人出來了才能再進去。
Semaphore(信號量)同一時間只允許一定數量的線程更改數據。
import threading, time def run(n): semaphore.acquire() time.sleep(1) print("run the thread: %s\n" % n) semaphore.release() if __name__ == '__main__': semaphore = threading.BoundedSemaphore(5) # 最多允許5個線程同時運行 '''每出來一個就會補充一個進去,限制線程裡面只有一定數量的線程在執行,確保同一時間只有五個併發執行''' for i in range(17): t = threading.Thread(target=run, args=(i,)) t.start() while threading.active_count() != 1: pass # print threading.active_count() else: print('----all threads done---')
運行結果如下:
run the thread: 0
run the thread: 3
run the thread: 4
run the thread: 1
run the thread: 2
run the thread: 7
run the thread: 8
run the thread: 6
run the thread: 5
run the thread: 9
run the thread: 10
run the thread: 14
run the thread: 11
run the thread: 12
run the thread: 13
run the thread: 16
run the thread: 15
----all threads done---
上面代碼中,限定了同一時間執行的線程個數,semaphore=threading.BoundedSemaphore(5)規定同一時間只有5個線程在執行,當裡面有線程執行完畢之後,就會有新的線程補充進來,知道所有線程都執行完畢。
Events(事件)
事件:狀態的切換,每一次狀態的切換會導致其他的變化,如紅綠燈。
時間:是一個非常簡單的事件同步對象;一個事件需要一個內部標誌。
event = threading.Event() #聲明一個event()對象
event.set() #設置一個全局變數,即標誌位
event.clear() #清空標誌位
event.set()相當於True,event.clear()相當於False。
event.wait()檢測標誌位是否設置,如果沒有設置,會一直卡在哪裡,不往下走。如果標誌位設置則不會堵塞,wait()等待標誌位被設置。
If the flag is set, the wait method doesn’t do anything.
標誌位設定了,代表綠燈,直接通行。
If the flag is cleared, wait will block until it becomes set again.
標誌位被清空,代表紅燈,wait()等待變路燈。
Any number of threads may wait for the same event.
每個線程都可以等待同一個事件。
下麵來寫一個紅綠燈的事件:
通過Event來實現兩個或多個線程間的交互,下麵是一個紅綠燈的例子,即起動一個線程做交通指揮燈,生成幾個線程做車輛,車輛行駛按紅燈停,綠燈行的規則。
import threading,time import random def light(): if not event.isSet(): event.set() #wait就不阻塞 #綠燈狀態 count = 0 while True: if count < 10: print('\033[42;1m--green light on---\033[0m') elif count <13: print('\033[43;1m--yellow light on---\033[0m') elif count <20: if event.isSet(): event.clear() print('\033[41;1m--red light on---\033[0m') else: count = 0 event.set() #打開綠燈 time.sleep(1) count +=1 def car(n): while 1: time.sleep(random.randrange(10)) if event.isSet(): #綠燈 print("car [%s] is running.." % n) else: print("car [%s] is waiting for the red light.." %n) if __name__ == '__main__': event = threading.Event() Light = threading.Thread(target=light) Light.start() for i in range(3): t = threading.Thread(target=car,args=(i,)) t.start()
紅綠燈:
import threading,time event = threading.Event() #聲明一個event事件對象 def lighter(): count = 0 event.set() while True: if count > 20 and count < 30: #改成紅燈 event.clear() #把標誌位清空 print("\033[41;1mred light is on.......\033[0m") elif count > 30: event.set() #設置標誌位,變綠燈 count = 0 #變成綠燈之後重新計數 else: print("\033[42;1mgreen linght in on ......\033[0m") time.sleep(1) count += 1 def car(name): while True: #檢測標誌位,存在則是綠燈,通行 if event.is_set(): #如果設置了標誌位,代表綠燈 print(