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()即調用此方法。
Python並行編程(二):基於線程的並行