Python並行程式設計(二):基於執行緒的並行
1、介紹
軟體應用中使用最廣泛的並行程式設計範例是多執行緒。通常一個應用有一個程序,分成多個獨立的執行緒,並行執行、互相配合,執行不同型別的任務。
執行緒是獨立的處理流程,可以和系統的其他執行緒並行或併發地執行。多執行緒可以利用共享記憶體空間共享資料和資源。執行緒和程序的具體實現取決於你要執行的作業系統,但是總體來講,我們可以說執行緒是包含在程序中的,同一個程序的多個不同的執行緒可以共享相同的資源,而程序之間不會共享資源。
每一個執行緒基本上包含3個元素:程式計數器,暫存器和棧。與同一程序的其他執行緒共享的資源基本上包括資料和系統資源。每一個執行緒也有自己的執行狀態,可以和其他執行緒同步,執行緒的狀態大體上可以分為ready,running,blocked。執行緒的典型應用是應用軟體的並行化,目的是為了充分利用現代的多核處理器,使每個核心可以執行單個執行緒。相比於程序,使用執行緒的優勢主要是效能,相比之下,在程序之間切換上下文要比在統一程序的多執行緒之間切換上下文要重的多。
2、定義一個執行緒
使用執行緒最簡單的方式是用一個目標函式例項化一個Thread然後呼叫start()方法啟動它。Python的threading模組提供了Thread()方法在不同的執行緒中執行函式或處理過程等。
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
- group:特性預留
- target:當執行緒啟動的時候要執行的函式
- name:執行緒的名字,預設為Thread-N
- args:傳遞給target的引數,要試用tuple型別
- kwargs:同上,試用欄位型別dict
執行緒程式碼用例:
import threading def function(i): print("I am thread-%s" %i) return threads = [] for i in range(5): t = threading.Thread(target=function, args=(i,)) threads.append(t) t.start() t.join()
t.join:主執行緒會呼叫t執行緒,然後等待t執行緒完成再執行for迴圈開啟下一個t執行緒。可理解為阻塞主執行緒。
3、確認一個執行緒
使用引數來確認或命名執行緒是沒有必要的,每一個Thread例項建立的時候都有一個帶預設值的名字,並且可以修改。在服務端通常一個服務程序都有多個執行緒服務,負責不同的操作,這時候命名執行緒是很實用的。
自定義執行緒名稱用例:
import threading import time def first_function(): print("%s is starting" %threading.currentThread().getName()) time.sleep(2) print("%s is exiting" %threading.currentThread().getName()) def second_function(): print("%s is starting" %threading.currentThread().getName()) time.sleep(2) print("%s is exiting" %threading.currentThread().getName()) def third_function(): print("%s is starting" %threading.currentThread().getName()) time.sleep(2) print("%s is exiting" %threading.currentThread().getName()) if __name__ == "__main__": t1 = threading.Thread(name='first_function', target=first_function) t2 = threading.Thread(name='second_function', target=second_function) t3 = threading.Thread(name='third_function', target=third_function) t1.start() t2.start() t3.start() t1.join() t2.join() t3.join()
執行結果:
如果不自定義名稱如下:
import threading import time def first_function(): print("%s is starting" %threading.currentThread().getName()) time.sleep(2) print("%s is exiting" %threading.currentThread().getName()) def second_function(): print("%s is starting" %threading.currentThread().getName()) time.sleep(2) print("%s is exiting" %threading.currentThread().getName()) def third_function(): print("%s is starting" %threading.currentThread().getName()) time.sleep(2) print("%s is exiting" %threading.currentThread().getName()) if __name__ == "__main__": # t1 = threading.Thread(name='first_function', target=first_function) # t2 = threading.Thread(name='second_function', target=second_function) # t3 = threading.Thread(name='third_function', target=third_function) t1 = threading.Thread(target=first_function) t2 = threading.Thread(target=second_function) t3 = threading.Thread(name='third_function', target=third_function) t1.start() t2.start() t3.start() t1.join() t2.join() t3.join()
執行結果:
4、使用執行緒
在子類中實現執行緒:
import threading import time exit_flag = 0 class myThread(threading.Thread): def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): print("Starting %s" %self.name) print_time(self.name, self.counter, 5) print("Exiting %s" %self.name) def print_time(threadName, delay, counter): while counter: if exit_flag: import _thread _thread.exit() time.sleep(delay) print("%s:%s" %(threadName, time.ctime(time.time()))) counter -= 1 # 建立例項 thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) thread1.start() thread2.start() thread1.join() thread2.join() print("Exiting Main Thread")
執行結果如下:
執行緒模組是建立和管理執行緒的首選形式。每一個執行緒都通過一個整合Thread的子類代表,覆蓋run()方法來實現邏輯,這個方法是執行緒的入門,執行start()即呼叫此方法。