地址:https://morvanzhou.github.io/tutorials/python-basic/threading/1-why/
多线程
一、添加线程
import threading
import time
def thread_job():
print("T1 start\n")
for i in range(10):
time.sleep(0.1) # 任务间隔0.1s
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
二、join功能
在上面例子基础上修改
def main():
added_thread = threading.Thread(target=thread_job, name='T1')
added_thread.start()
added_thread.join() #等待该线程运行完才运行后面语句
print("all done\n")
三、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): #创建四个线程,每个线程一个小队列
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): #把结果放到results中打印
results.append(q.get())
print(results)
if __name__ == '__main__':
multithreading()
四、GIL(Global Interpreter Lock )不一定有效率,纯运算速度没有提升太高
测试:
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.29871177673339844
1999998000000
multithreading: 0.2837047576904297
使用了多线程但是对于纯运算速度没有提升太高,同一时刻只有一个核在运算
后面会用到多核的运算
五、线程锁:为了让A完成后在处理B
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()
不知道为什么我不用lock也没有冲突