多线程可以加速程序的运算,此笔记为python的多线程模块threading的学习笔记。来自莫凡大神视频学习笔记 莫凡python-threading
添加线程
import threading
threading.active_count()#获取已经激活的线程数
# 1
threading.enumerate()#查看所有的线程信息
# [<_MainThread(MainThread, started 4088)>]
#多线程为一个_MainThread带多个Thread
threading.current_thread()#查看当前运行的进程
# <_MainThread(MainThread, started 11136)>
#添加线程threading.Thread()
#接收参数target代表这个线程要完成的任务,需自行定义
def target_job():
print("This is a thread of %s"%threading.current_thread())
def main():
thread=threading.Thread(target=target_job,)#定义线程
thread.start()#线程工作
main( )
#This is a thread of <Thread(Thread-1, started 12692)>
join之进程执行的顺序
import threading
import time
def thread( ):
print("T START")
for i in range(100):
time.sleep(0.1)
print("T end")
add_thread=threading.Thread(target=thread,name='T')
add_thread.start()
print("all over")
实际执行效果:
T START
all over
T end
线程任务还未完成便输出all over
import threading
import time
def thread( ):
print("T START")
for i in range(100):
time.sleep(0.1)
print("T end")
add_thread=threading.Thread(target=thread,name='T')
add_thread.start()
add_thread.join()#加入join,遵循顺序输出
print("all over")
T START
T end
all over
当两个线程时,由于任务2比任务1轻量级,会率先完成,且all over 的执行顺序取决于其他线程的执行速度。如下所示:
def thread1( ):
print("T1 START")
for i in range(10):
time.sleep(0.1)
print("T1 end")
def thread2( ):
print("T2 START")
print("T2 end")
add_thread1=threading.Thread(target=thread1,name='T1')
add_thread2=threading.Thread(target=thread2,name='T2')
add_thread1.start()
add_thread2.start()
print("all over")
结果:
T1 START
T2 START
all over
T2 end
T1 end
当T1加入join后:
add_thread1=threading.Thread(target=thread1,name='T1')
add_thread2=threading.Thread(target=thread2,name='T2')
add_thread1.start()
add_thread1.join()
add_thread2.start()
print("all over")
结果:
T1 START
T1 end
T2 START
T2 end
all over
当T2加入join后,下面1122的加法会使得轻量级任务率先完成。但all over还是最后执行。
dd_thread1=threading.Thread(target=thread1,name='T1')
add_thread2=threading.Thread(target=thread2,name='T2')
add_thread1.start()
add_thread2.start()
add_thread1.join()
add_thread2.join()
print("all over")
结果:
T1 START
T2 START
T2 end
T1 end
all over
当采用1212加法后,遵循正常顺序
add_thread1=threading.Thread(target=thread1,name='T1')
add_thread2=threading.Thread(target=thread2,name='T2')
add_thread1.start()
add_thread1.join()
add_thread2.start()
add_thread2.join()
print("all over")
结果:
T1 START
T1 end
T2 START
T2 end
all over
存储进程结果Queue
导入线程,队列的标准模块
定义一个被多线程调用函数
定义一个多线程函数
import threading
import time
from queue import Queue
#将数据列表数据传入,四此案成处理,结果保存在Queue中,线程执行完后,
# 从Queue中获取存储结果
#多线程调用的函数不能用return返回值
#被多线程调用的函数
def work(l,q):
for i in range(len(l)):
l[i]=l[i]**2
q.put(l)
#定义多线程函数,定义4个线程
def multi_thread():
q=Queue()#q中存放返回值
threads=[]#存放4线程
data=[[1,2,3],[4,5,6],[7,8,9],[3,4,5]]
#定义线程
for i in range(4):
Ts = threading.Thread(target=work, args=(data[i],q))
Ts.start()
threads.append(Ts)#每个线程append列表中
#执行线程
for t in threads:
t.join( )
#用空列表接收队列中的结果
results=[]
for _ in range(4):
results.append(q.get())
print(results)
multi_thread()
结果:
[[1, 4, 9], [16, 25, 36], [49, 64, 81], [9, 16, 25]]
GIL(Global Interpreter Lock)
GIL让python任何时候只能执行一个python线程,因为解释器的C语言实现部分在完全并行执行时并不是线程安全的,解释器被一个全局解释器锁保护。GIL最大的问题时python的多线程程序不能利用多核CPU优势,影响到那些严重依赖CPU的程序。
import threading
import copy
import time
from queue import Queue
#多线程调用的函数不能用return返回值
#被多线程调用的函数
def work(l,q):
res=sum(l)
q.put(res)
#定义多线程函数,定义4个线程
def multi_thread(I):
q=Queue()#q中存放返回值
threads=[]#存放4线程
#定义线程
for i in range(4):
Ts = threading.Thread(target=work, args=(copy.copy(I),q),name="T%i"%i)
Ts.start()
threads.append(Ts)#每个线程append列表中
#执行线程
for t in threads:
t.join( )
total=0
for _ in range(4):
total=total+q.get()
print(total)
#定义一个普通函数
def f(I):
s=sum(I)
print(s)
I=list(range(10000))
t=time.time()
f(I*4)
print("normal:",time.time()-t)
t2=time.time()
multi_thread(I)
print("multithreading:",time.time()-t2)
结果:
99980000
normal: 0.0010018348693847656
199980000
multithreading: 0.001976490020751953
理应利用多线程会变快,但并没有。
线程锁lock
不使用LOCK,打印混乱,使用lock,利用acquire,release将共享内存上锁,确保内存独占性。
import threading
def work1():
global a
lock.acquire()
for i in range(10):
a=a+1
print("work1",a)
lock.release()
def work2():
global a
lock.acquire()
for i in range(10):
a = a + 10
print("work2", a)
lock.release()
lock=threading.Lock( )
a=0
w1=threading.Thread(target=work1)
w2=threading.Thread(target=work2)
w1.start()
w2.start()
w1.join()
w2.join()
结果:
work1 1
work1 2
work1 3
work1 4
work1 5
work1 6
work1 7
work1 8
work1 9
work1 10
work2 20
work2 30
work2 40
work2 50
work2 60
work2 70
work2 80
work2 90
work2 100
work2 110