python 之 Threading 多线程
参考视频:莫烦python https://mofanpy.com/tutorials/python-basic/threading/why/
1.多线程简单介绍
# -*- coding: utf-8 -*- import threading def main(): print(threading.active_count()) #运行的线程个数 print(threading.enumerate()) #运行的是哪些线程 print(threading.current_thread()) #当下运行的是哪个线程 if __name__ == 'main': main()
6
[<_MainThread(MainThread, started 13824)>, <Thread(Thread-4, started daemon 1452)>, <Heartbeat(Thread-5, started daemon 14768)>, <HistorySavingThread(IPythonHistorySavingThread, started 4796)>, <ParentPollerWindows(Thread-3, started daemon 1852)>, <GarbageCollectorThread(Thread-6, started daemon 992)>]
<_MainThread(MainThread, started 13824)>
2.添加多线程
# -*- coding: utf-8 -*- import threading def thread_job(): print('This is an added Theard,number is %s' % threading.current_thread()) def main(): added_thread = threading.Thread(target=thread_job) added_thread.start() if __name__ == 'main': main()
This is an added Theard,number is <Thread(Thread-10, started 8780)>
3. join 功能
# -*- coding: utf-8 -*- 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 main(): added_thread = threading.Thread(target=thread_job,name="T1") added_thread.start() print("all done\n") if __name__ == 'main': main()
T1 start
all done
T1 finish
可以看出,all done 在 T1 finish 之前,多个线程是同时执行的。要想让 all done 输出在 T1 finish 后面,可以用 joint。
# -*- coding: utf-8 -*- 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 main(): added_thread = threading.Thread(target=thread_job,name="T1") added_thread.start() added_thread.join() print("all done\n") if __name__ == 'main': main()
T1 start
T1 finish
all done
再一个例子
# -*- coding: utf-8 -*-
import threading
import ti
def thread_job(): print("T1 start\n") for i in range(10): time.sleep(0.1) print("T1 finish\n") def thread_job2(): print("T2 start\n") print("T2 finish\n") def main(): added_thread = threading.Thread(target=thread_job,name="T1") added_thread2 = threading.Thread(target=thread_job2,name="T2") added_thread.start() added_thread2.start() #added_thread.join()
#added_thread2.join()
print("all done\n") if __name__ == 'main': main()
T1 start
T2 start
T2 finish
all done
T1 finish
有了 added_thread.join() 以后,输出变为
T1 start
T2 start
T2 finish
T1 finish
all done
4. Queue 功能
用于装多线程的运算结果
# -*- coding: utf-8 -*- import threading from queue import Queue def job(l,q): for i in range(len(l)): l[i] = l[i]**2 q.put(l) #将计算结果放入q,不能用return def multiThreading(): q = Queue() threads=[] #装四个线程 data = [[1,2,3],[4,5,6],[6,6,6],[8,8,8]] for i in range(4):#分别运行四个线程并传入参数 t = threading.Thread(target=job,args=(data[i],q)) t.start() threads.append(t) for thread in threads: thread.join() results=[] #将结果一个个取出到 results 并输出 for _ in range(4): results.append(q.get()) print(results) if __name__=="__main__": multiThreading()
[[1, 4, 9], [16, 25, 36], [36, 36, 36], [64, 64, 64]]
5. 多线程控制 GIL
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)
1999998000000
normal: 0.15854287147521973
1999998000000
multithreading: 0.14863324165344238
6. 锁 lock
如果没有锁
import threading def job1(): global A for i in range(10): A+=1 print('job1',A) def job2(): global A for i in range(10): A+=10 print('job2',A) if __name__== '__main__': A=0 t1=threading.Thread(target=job1) t2=threading.Thread(target=job2) t1.start() t2.start() t1.join() t2.join()
job1 1
job1 2
job1 3
job1 4
job1 5
job1 6
job1 7
job1 8
job1 9
job1 job2 20
job2 30
job2 40
job2 50
job2 60
job2 70
job2 8010
job2 90
job2 100
job2 110
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()
job1 1
job1 2
job1 3
job1 4
job1 5
job1 6
job1 7
job1 8
job1 9
job1 10
job2 20
job2 30
job2 40
job2 50
job2 60
job2 70
job2 80
job2 90
job2 100
job2 110