任務能夠由多進程完成,也能夠由一個進程內的多線程完成。
咱們前面提到了進程是由若干線程組成的,一個進程至少有一個線程。
因爲線程是操做系統直接支持的執行單元,所以,高級語言一般都內置多線程的支持,Python也不例外,而且,Python的線程是真正的Posix Thread,而不是模擬出來的線程。Python的標準庫提供了threading模塊。html
在python中多線程的實現方法有2種。python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import threading def worker(args): print("開始子進程 {0}".format(args)) print("結束子進程 {0}".format(args)) if __name__ == '__main__': print("start main") t1 = threading.Thread(target=worker, args=(1,)) t2 = threading.Thread(target=worker, args=(2,)) t1.start() t2.start() print("end main") |
輸出結果多線程
1 2 3 4 5 6 |
start main 開始子進程 1 結束子進程 1 開始子進程 2 結束子進程 2 end main |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import threading import time class Hello(threading.Thread): def __init__(self, args): super(Hello, self).__init__() #注意:要顯式的調用父類的初始化函數 self.args = args def run(self): print("開始子進程 {0}".format(self.args)) time.sleep(1) print("結束子進程 {0}".format(self.args)) if __name__ == '__main__': a = 1 print("start main") t1 = Hello(1) t2 = Hello(2) t1.start() t2.start() print("end main") |
輸出結果併發
1 2 3 4 5 6 |
start main 開始子進程 1 開始子進程 2 end main 結束子進程 1 結束子進程 2 |
enumerate()
列表長度相等。thread identifier
。這是個非零的整數。該值無特殊含義。current_thread()
建立的虛擬線程對象,不包括已結束和還沒開始的線程。RuntimeError
錯誤。RuntimeError
錯誤。假如主線程不是守護線程,該主線程建立的全部子線程該值爲False。 threading.Lock()
進行,操做相似於多進程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import threading import time def worker(name, lock): with lock: print("start {0}".format(name)) time.sleep(5) print("end {0}".format(name)) if __name__ == "__main__": lock = threading.Lock() t1 = threading.Thread(target=worker, args=("worker1", lock)) t2 = threading.Thread(target=worker, args=("worker2", lock)) t1.start() t2.start() |
輸出結果app
1 2 3 4 |
start worker1 end worker1 start worker2 end worker2 |
固然,獲取鎖也能夠經過lock.acquire()
完成,釋放鎖經過lock.release()
完成。ide
1 2 3 4 5 6 7 8 |
def worker(name, lock): lock.acquire() try: print("start {0}".format(name)) time.sleep(5) print("end {0}".format(name)) finally: lock.release() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import threading l = list() l += range(1, 4) def worker(): l.append("GOD") if __name__ == "__main__": t1 = threading.Thread(target=worker) t2 = threading.Thread(target=worker) t1.start() t2.start() print(l) |
輸出結果函數
1 |
[1, 2, 3, 'GOD', 'GOD'] |
在使用多線程處理任務時也不是線程越多越好,因爲在切換線程的時候,須要切換上下文環境,依然會形成cpu的大量開銷。爲解決這個問題,線程池的概念被提出來了。預先建立好一個較爲優化的數量的線程,讓過來的任務馬上可以使用,就造成了線程池。
此處介紹threapool
是一個第三方模塊,須要使用pip install threadpool
安裝。優化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import threadpool def hello(m, n, o): print("m = {0} n={1} o={2}".format(m, n, o)) if __name__ == '__main__': lst_vars_1 = ['1', '2', '3'] lst_vars_2 = ['4', '5', '6'] func_var = [(lst_vars_1, None), (lst_vars_2, None)] pool = threadpool.ThreadPool(2) requests = threadpool.makeRequests(hello, func_var) [pool.putRequest(req) for req in requests] pool.wait() |
輸出結果ui
1 2 |
m = 1 n=2 o=3 m = 4 n=5 o=6 |
Executor Objects
,更多內容點擊concurrent.futures — Launching parallel tasks查看官方介紹。threading
的內容能夠點擊threading — Thread-based parallelism查看官方介紹。