基于線程的并行-Python 并行編程學習筆記(一)
前言
最近寫一些模擬集群智能的算法,雖然機制簡單,但是隨著個體的增加,設計的計算量就比較大了,尤其是加上matplotlib進行動態展示,使得運算量驟增,看著畫面也比較卡.之前想把算法轉化成c++代碼,利用qt進行展示,入了坑才發現不是一朝一夕之功??????,沒辦法,還是回到自己熟悉的python上看看能不能優化一下代碼.然后買了<<Python 并行編程-第二版>>這本書從頭學起,希望用兩三個月把這個整個七七八八.我相信我能堅持下去,把這塊骨頭啃明白.算是一個學習筆記吧,加上一些自己的理解,如果有哪位看官看到此文,發現講到不對的地方加以批評指正.
基于線程的并行
threading模塊提供的Thread類
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
主要的參數就三個:
- target:線程要執行的目標函數
- name:線程名
- args:目標函數的參數
下面是一個簡單的例子:
import threading
import time
import random
def sleep_out(i):
print("{}號程序開始執行\n".format(i))
num = random.randint(0, 10)
time.sleep(num)
print("{}號程序休息了{}s\n".format(i,num))
if __name__ == "__main__":
threads = []
for i in range(10):
t = threading.Thread(target=sleep_out, args=(i,), name="thread-{}".format(i))
threads.append(t)
for t in threads:
t.start()
for t in threads:
t.join()
-----------------------------------輸出-----------------------------
0號程序開始執行
1號程序開始執行
2號程序開始執行
3號程序開始執行
4號程序開始執行
5號程序開始執行
6號程序開始執行
7號程序開始執行
8號程序開始執行
9號程序開始執行
8號程序休息了1s
7號程序休息了4s
6號程序休息了5s
2號程序休息了6s
4號程序休息了7s
0號程序休息了7s
3號程序休息了8s
1號程序休息了10s
9號程序休息了10s
5號程序休息了10s
進程已結束,退出代碼0
線程開始執行使用start()方法,一旦線程開始執行,則運行會轉入后臺,主線程繼續執行.而要等待一個線程結束,必須使用join()方法,該方法會讓主線程進入等待狀態,直到線程執行完畢,主線程才會繼續執行.
我們將剛才的程序改寫為:
import threading
import time
import random
def sleep_out(i):
print("{}號程序開始執行\n".format(i))
num = random.randint(0, 10)
time.sleep(num)
print("{}號程序休息了{}s\n".format(i,num))
if __name__ == "__main__":
threads = []
for i in range(10):
t = threading.Thread(target=sleep_out, args=(i,), name="thread-{}".format(i))
threads.append(t)
t.start()
t.join()
-----------------------------------輸出-----------------------------
0號程序開始執行
0號程序休息了6s
1號程序開始執行
1號程序休息了6s
2號程序開始執行
2號程序休息了8s
3號程序開始執行
3號程序休息了0s
4號程序開始執行
4號程序休息了5s
5號程序開始執行
5號程序休息了1s
6號程序開始執行
6號程序休息了8s
7號程序開始執行
7號程序休息了8s
8號程序開始執行
8號程序休息了10s
9號程序開始執行
9號程序休息了9s
進程已結束,退出代碼0
start()方法和join()方法相輔相成,一般不能獨立存在.
確定當前線程
使用currentThread().getName()方法會返回當前線程名.
繼續在剛才的代碼上修改:
import threading
import time
import random
def sleep_out(i):
print("{}號程序開始執行\n".format(i))
print("當前線程為"+threading.currentThread().getName())
num = random.randint(0, 10)
time.sleep(num)
print("{}號程序休息了{}s\n".format(i,num))
if __name__ == "__main__":
threads = []
for i in range(10):
t = threading.Thread(target=sleep_out, args=(i,), name="thread-{}".format(i))
threads.append(t)
t.start()
t.join()
-----------------------------------輸出-----------------------------
0號程序開始執行
當前線程為thread-0
0號程序休息了2s
1號程序開始執行
當前線程為thread-1
1號程序休息了2s
2號程序開始執行
當前線程為thread-2
2號程序休息了3s
3號程序開始執行
當前線程為thread-3
3號程序休息了1s
4號程序開始執行
當前線程為thread-4
4號程序休息了3s
5號程序開始執行
當前線程為thread-5
5號程序休息了1s
6號程序開始執行
當前線程為thread-6
6號程序休息了2s
7號程序開始執行
當前線程為thread-7
7號程序休息了1s
8號程序開始執行
當前線程為thread-8
8號程序休息了1s
9號程序開始執行
當前線程為thread-9
9號程序休息了4s
進程已結束,退出代碼0
自定義線程類
我們可以創建繼承Thread類的子類,再重新定義run()方法,實現自己需要的功能.
示例如下:
import time
import threading
from random import randint
import os
def sleep_out(num):
time.sleep(num)
class MyThreadClass(threading.Thread):
def __init__(self, name, duration):
threading.Thread.__init__(self)
self.name = name
self.duration = duration
def run(self):
print("線程:" + self.name + "正在運行, 進程ID:" + str(os.getpid()))
sleep_out(self.duration)
print("線程" + self.name + "結束!!!")
if __name__ == "__main__":
start_time = time.time()
threads = []
for i in range(10):
t = MyThreadClass(name="thread-{}".format(i), duration=randint(0, 5))
threads.append(t)
for t in threads:
t.start()
for t in threads:
t.join()
print("-----{}-----".format(time.time() - start_time))
----------輸出----------
線程:thread-0正在運行, 進程ID:11804
線程thread-0結束!!!
線程:thread-1正在運行, 進程ID:11804
線程:thread-2正在運行, 進程ID:11804
線程:thread-3正在運行, 進程ID:11804
線程:thread-4正在運行, 進程ID:11804
線程:thread-5正在運行, 進程ID:11804
線程:thread-6正在運行, 進程ID:11804
線程:thread-7正在運行, 進程ID:11804
線程:thread-8正在運行, 進程ID:11804
線程:thread-9正在運行, 進程ID:11804
線程thread-6結束!!!線程thread-8結束!!!
線程thread-5結束!!!
線程thread-7結束!!!
線程thread-9結束!!!
線程thread-2結束!!!線程thread-3結束!!!
線程thread-1結束!!!線程thread-4結束!!!
-----5.019770860671997-----

浙公網安備 33010602011771號