Python多线程笔记记录
2020-12-30 02:40 那个杰克 阅读(117) 评论(0) 收藏 举报顿悟,需要多学习,多写笔记,以谢罪天下!
线程的多种实现方法:
Thread模块
Treading模块
Queue模块 -- 未学习
先说一下Thread模块,Thread模块会带上锁机制GIL (global interpreter lock 全局解释锁),简单理解就是让线程,不会因为主线程的退出,导致线程直接终止运行
直接上代码
如果平时不用多线程开发,是这样子的
from time import ctime,sleep
def loop0():
print("start loop0 at",ctime())
sleep(4)
print("start loop0 at",ctime())
def loop1():
print("start loop1 at",ctime())
sleep(2)
print("start loop1 at",ctime())
def main():
print("开始:",ctime())
loop0()
loop1()
print("结束:",ctime())
运行结果:
开始: Wed Dec 30 02:32:44 2020
start loop0 at Wed Dec 30 02:32:44 2020
start loop0 at Wed Dec 30 02:32:48 2020
start loop1 at Wed Dec 30 02:32:48 2020
start loop1 at Wed Dec 30 02:32:50 2020
结束: Wed Dec 30 02:32:50 2020
loop0 和 loop1 首次输出结果相差了4秒,没有并行执行
[Finished in 6.2s]
如果线程没有锁的情况下:
无锁机制
import _thread
import time
def loop0():
print("start loop0 at:-->",time.ctime())
time.sleep(4)
print("start loop0 at:-->",time.ctime())
def loop1():
print("start loop1 at:-->",time.ctime())
time.sleep(2)
print("start 1 done at:-->",time.ctime())
def main():
print("starting at:-->",time.ctime())
_thread.start_new_thread(loop0,())
_thread.start_new_thread(loop1,())
#
#time.sleep(6)
print("all done at:-->",time.ctime())
if __name__=="__main__":
main()
注释: 如果去掉time.sleep(6),等待主线程退出的机制。主进程退出后,正在运行的线程就直接退出了
运行结果:
未注释time.sleep(6),卡住主线程
tarting at:--> Wed Dec 30 02:19:11 2020
start loop0 at:--> Wed Dec 30 02:19:11 2020
start loop1 at:--> Wed Dec 30 02:19:11 2020
start 1 done at:--> Wed Dec 30 02:19:13 2020
start loop0 at:--> Wed Dec 30 02:19:15 2020
all done at:--> Wed Dec 30 02:19:17 2020
loop0 和 loop1 首次输出结果时间相同,并行执行了
[Finished in 6.2s] 总共运行6.2秒
注释time.sleep(6)后,直接进入主线程
starting at:--> Wed Dec 30 02:01:48 2020
all done at:--> Wed Dec 30 02:01:48 2020
[Finished in 0.2s]
全部执行完:0.2秒,线程没执行完即终止
import _thread
from time import sleep,ctime
loops=[4,2]
def loop(nloops,nsec,lock):
print("start loop","->",nloops,"《标志位》","at:",ctime())
sleep(nsec)
print("loop",nloops,"《标志位》","->",'doop at:',ctime())
lock.release() #3.释放锁
def main():
print("starting at:",ctime())
#生产几把锁,放到队列里
locks=[]
#生成索引
nloops=range(len(loops))
#创建锁
for i in nloops:
lock = _thread.allocate_lock() #创建一把锁 -- 1.创建锁
lock.acquire() #加上这句,给锁自动对对象上锁 --2.获得锁
locks.append(lock)
for i in nloops:
_thread.start_new_thread(loop,(i,loops[i],locks[i]))
for i in nloops:
while locks[i].locked(): #判断锁的状态,如果处于被锁状态,一次处于等待,拖住主线程 --4.检查锁
pass
print('all DONE at:',ctime())
if __name__=="__main__":
main()
不需要加time.sleep(),卡住主进程,主进程也会等待线程运行完成,且解锁后,才停止
运行效果:
starting at: Wed Dec 30 02:03:17 2020
start loop 0 ->《标志位》 at:0 Wed Dec 30 02:03:17 2020
start loop 1 ->《标志位》
at: Wed Dec 30 02:03:17 2020
loop 1 《标志位》 -> doop at: Wed Dec 30 02:03:19 2020
loop 0 《标志位》 -> doop at: Wed Dec 30 02:03:21 2020
all DONE at: Wed Dec 30 02:03:21 2020
[Finished in 4.5s] 执行4.5秒
*一般已经放弃使用Thread创建线程,因为Thread创建的线程,如果一旦主进程异常终止或者认为终止,所有状态的线程都会终止
使用Threading模块:
使用Threading模块有三种方式,看主要喜欢的方式,官方推荐使用第三种
- 创建一个Thread的实例,传给它一个函数,t=threading.Thread() t(target=xxx,args=xxx)
- 创建一个Thread的实例,传给它一个可调用的类对象
- 从Thread派生出一个子类,创建一个这个子类的实例
使用的好处:
1.不需要创建各种状态的锁机制(分配锁,获得锁,释放锁,检查锁)
2.主线程需要等待守护线程结束后才终止
方式一:
import threading
from time import sleep,ctime
loops=[4,2]
def loop(nloop,nsec):
print("start loop",nloop,'at:',ctime())
sleep(nsec)
print("loop",nloop,"done at:",ctime())
def main():
print("starging at:",ctime())
threads=[]
nloops=range(len(loops))
for i in nloops:
t=threading.Thread(target=loop,args=(i,loops[i]))
threads.append(t)
for i in nloops: #start threads
threads[i].start()
for i in nloops:
pass=
#threads[i].join()
print("all DONE at:",ctime())
if __name__=="__main__":
main()
运行结果:
starging at: Wed Dec 30 02:17:24 2020
start loop 0 at: Wed Dec 30 02:17:24 2020
start loop 1 at: Wed Dec 30 02:17:24 2020
loop 1 done at: Wed Dec 30 02:17:26 2020
loop 0 done at: Wed Dec 30 02:17:28 2020
all DONE at: Wed Dec 30 02:17:28 2020
[Finished in 4.2s] 执行完:4.2秒
方式三:
import threading
from time import ctime,sleep
loops = [4,2]
class MyThread(threading.Thread):
def __init__(self,func,args,name=''):
#创建子类构建器时,必须要先调用基类的构造器
threading.Thread.__init__(self)
self.name=name
self.func=func
self.args=args
def run(self):
self.func(*self.args)
def loop(nloop,nsec):
print("start loop",nloop,"at:",ctime())
sleep(nsec)
print("loop",nloop,"done at:",ctime())
def main():
print("starting at:",ctime())
threads=[]
nloops=range(len(loops))
for i in nloops:
t = MyThread(loop,(i,loops[i]),loop.__name__)
threads.append(t)
for i in nloops:
threads[i].start()
for i in nloops:
threads[i].join()
print("all Done at:",ctime())
if __name__=="__main__":
main()
运行结果:
starting at: Wed Dec 30 02:21:22 2020
start loop 0 at: Wed Dec 30 02:21:22 2020
start loop 1 at: Wed Dec 30 02:21:22 2020
loop 1 done at: Wed Dec 30 02:21:24 2020
loop 0 done at: Wed Dec 30 02:21:26 2020
all Done at: Wed Dec 30 02:21:26 2020
[Finished in 4.2s] 总共运行4.2秒
学习点:
-
join() 线程挂起 --主线程需要等所有挂起的线程结束后,才开始继续执行
-
isAlive() 查看线程是否处于运行状态
-
start() 开始线程的执行
-
setDaemon(True) 设置成不是守护线程,表示线程不重要,类似于,设置这个标签,表示你不是vip,主线程可以随时轰你走(主线程终止,即线程终止)
使用join挂起线程的应用场景:
希望线程运行结束后,主线程才执行,比如:等待客户输入完成
不使用join挂起线程的应用场景:
希望主线程运行的同时,线程也在同步运行,比如:???
浙公网安备 33010602011771号