Python3線程
很大一堆數據需要處理,加速效率使用多線程可以節省運算的時間。
多線程基礎
-
threading.active_count() 目前多少個激活的線程
-
threading.enumerate() 枚舉當前正在運行的多線程
-
threading.current_thread() 當前程序運行的進程是哪個線程
-
基本用法
target : 指定 這個線程去哪個函數里面去執行代碼
args: 指定將來調用 函數的時候 傳遞什么數據過去
args參數指定的一定是一個元組類型
name屬性是命名多線程的名字
start()是開始執行多線程
join()是線程結束后再執行后來的語句才會用到
示例代碼:
thread = threading.Thread(target=thread_job,)
thread.start()
thread_job函數是輸出一個當前正在運行的線程名稱,完整代碼。
import threading
#def main():
# print(threading.active_count())
# print(threading.enumerate()) # see the thread list
# print(threading.current_thread())
def thread_job():
print('This is a thread of %s' % threading.current_thread())
def main():
thread = threading.Thread(target=thread_job,)
thread.start()
if __name__ == '__main__':
main()
join應用
想要等待所有多線程運行完畢后再顯示出all done\n
,才需要用到join語句。
import threading
import time
def thread_job():
print('T1 start\n')
for i in range(10):
time.sleep(0.1)
print('T1 finish\n')
def T2_job(temp):
print('T2 start\n')
print("-----in test2 temp=%s-----"% str(temp))
print('T2 finish\n')
def main():
added_thread = threading.Thread(target=thread_job, name='T1')
thread2 = threading.Thread(target=T2_job, args=(g_nums,), name='T2')
added_thread.start()
thread2.start()
thread2.join()
added_thread.join()
print('all done\n')
if __name__ == '__main__':
main()
Queue應用
多線程的結果是沒有返回值的,可以把所有線程結果放到長隊列中運算然后再取出來。
import threading
import time
from queue import Queue
def job(l,q): # 執行函數
for i in range(len(l)):
l[i] = l[i]**2
q.put(l) # 把結果加入到隊列中
def multithreading():
q = Queue()
threads = []
data = [[1,2,3],[3,4,5],[4,4,4],[5,5,5]]
for i in range(4): # 定義4個線程
t = threading.Thread(target=job, args=(data[i], q))
t.start()
threads.append(t)
for thread in threads:
thread.join() # 結束后再執行接下來的內容
results = []
for _ in range(4): # 從4個線程里面得到結果,按順序拿出結果
results.append(q.get())
print(results)
if __name__ == '__main__':
multithreading()
GIL
Python不是真正意義上的多線程而是在多個線程中快速切換。
import threading
from queue import Queue
import copy
import time
def job(l, q):
res = sum(l)
q.put(res)
def multithreading(l):
q = Queue()
threads = []
for i in range(4):
t = threading.Thread(target=job, args=(copy.copy(l), q), name='T%i' % i)
t.start()
threads.append(t)
[t.join() for t in threads]
total = 0
for _ in range(4):
total += q.get()
print(total)
def normal(l):
total = sum(l)
print(total)
if __name__ == '__main__':
l = list(range(1000000))
s_t = time.time()
normal(l*4)
print('normal: ',time.time()-s_t)
s_t = time.time()
multithreading(l)
print('multithreading: ', time.time()-s_t)
lock
第一個線程處理完結果,然后第二個線程用的時候。會用到鎖,在第一個線程處理時,第二個線程暫時無法操作。等第一個線程執行完畢之后才可以接下來的操作。
A是一個全局變量,當兩個線程對同一個變量進行操作。那么就在操作A的時候鎖住其他線程。然后當操作完畢之后再讓第二個線程操作。
import threading
def job1():
global A, lock # 開始鎖線程
lock.acquire()
for i in range(10):
A += 1
print('job1', A)
lock.release() # 釋放鎖
def job2():
global A, lock
lock.acquire()
for i in range(10):
A += 10
print('job2', A)
lock.release()
if __name__ == '__main__':
lock = threading.Lock()
A = 0
t1 = threading.Thread(target=job1)
t2 = threading.Thread(target=job2)
t1.start()
t2.start()
t1.join()
t2.join()
參考
https://www.bilibili.com/video/av16944429/?p=5
https://github.com/MorvanZhou/tutorials/tree/master/threadingTUT