视频地址:Threading 学会多线程 (莫烦 Python 教程)
文字参考:Python3 多线程 | 菜鸟教程
添加线程
import threading
def thread_job():
#显示这个线程的名字
print('This is an added Thread,number is %s'% threading.current_thread)
def main():
#创建一个线程,线程工作内容为target
added_thread = threading.Thread(target=thread_job)
#创建的thread开始工作
added_thread.start()
#查看现在有多少个激活了的线程
print(threading.active_count())
#查看激活的进程是哪两个
print(threading.enumerate())
#查看当前运行的线程是哪个线程
print(threading.current_thread())
if __name__=='__main__':
main()
join功能
import threading
import time
def thread_job():
print('T1 start\n')
for i in range(10):
#休眠0.1秒
time.sleep(0.1)
print('T1 finish\n')
def T2_job():
print('T2 strat\n')
print('T2 finish\n')
def main():
#创建一个线程,线程工作内容为target,线程命名为T1
added_thread = threading.Thread(target=thread_job,name='T1')
thread2 = threading.Thread(target=T2_job,name='T2')
#创建的thread开始工作
added_thread.start()
thread2.start()
#若不加的话,会先显示all done,加了之后,要等前面的程序结束了才运行后面
#也就是说影响的是主线程的速度
added_thread.join()
thread2.join()
print('all done\n')
if __name__=='__main__':
main()
Queue功能
多线程没有返回值,所以要把结果放在长的队列当中,对每个线程中的队列,到主线程后再拿出来
threading.Thread(target=job,args=(data[i])),job后面不需要加括号,因为参数在args里面
for循环若没有用到参数只是为了循环计算,可以用_代替
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]]
#定义4个线程
for i in range(4):
t = threading.Thread(target=job,args=(data[i],q))
t.start()
#将线程t加入到全部线程当中
threads.append(t)
#将所有线程加到主线程里,当所有线程运行完后才运行主线程
for thread in threads:
thread.join()
results = []
#没有用到参数只是为了循环计算,因此用_
for _ in range(4):
#从q里每次拿出一个值
results.append(q.get())
print(results)
if __name__=='__main__':
multithreading()
不一定有效率的GIL
按理来说, 我们预期会要快3-4倍, 因为有建立4个线程, 但是并没有. 这就是其中的 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)
锁Lock
用法:如果线程1先处理完得到一个初步结果,再将这个结果放到线程2处理,先等线程1处理完,要先锁住线程2
若无lock,会print到一半就被别的线程插入
加了lock后,会print完一段后才接入别的进程
被lock.acquire()和lock.release()围住的内容,只有print完一次之后,才让别的线程运行,或者说当他要准备print时,会lock住,不让别的线程运行
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()