提到多线程,很多人就会望而却步,本文将由浅入深地带你攻克python多线程编程,并防止你跳入深坑,
首先看一段简单的代码:
1 from time import ctime,sleep 2 def play_video(video): 3 for i in range(2): 4 print "i am playing video: %s at %s"%(video,ctime()) 5 sleep(4) 6 7 8 def play_music(music): 9 for i in range(2): 10 print "i am playing music: %s at %s"%(music,ctime()) 11 sleep(2) 12 13 14 if __name__=="__main__": 15 16 play_video("speed_and_crazy") 17 play_music("chengdu") 18 19 print "all are over at %s"%ctime() 20 21
执行结果:
C:\Python27>python mui_thread.py i am playing video: speed_and_crazy at Mon Jun 26 23:01:59 2017 i am playing video: speed_and_crazy at Mon Jun 26 23:02:03 2017 i am playing music: chengdu at Mon Jun 26 23:02:07 2017 i am playing music: chengdu at Mon Jun 26 23:02:09 2017 all are over at Mon Jun 26 23:02:11 2017
随着人们对多任务的要求,同时为了充分利用cpu资源,多线程编程不可避免,那么我们如何利用python去实现play_video和play_music
两个任务同时运行呢?
1 from time import ctime,sleep 2 import threading 3 def play_video(video): 4 for i in range(2): 5 print "i am playing video: %s at %s \n"%(video,ctime()) 6 sleep(5) 7 8 9 def play_music(music): 10 for i in range(2): 11 print "i am playing music: %s at %s \n"%(music,ctime()) 12 sleep(1) 13 14 threads=[] 15 16 thread1=threading.Thread(target=play_video,args=("speed_and_crazy",)) 17 18 threads.append(thread1) 19 20 thread2=threading.Thread(target=play_music,args=("chengdu",)) 21 22 threads.append(thread2) 23 24 25 26 if __name__=="__main__": 27 28 for thread in threads: 29 thread.setDaemon(True) #将线程声明为守护线程,必须在start()方法调用之前,如果不设置为守护线程,程序会被无限挂起 30 thread.start() 31 32 print "all are over at %s \n"%ctime() 33 34
测试结果:
C:\Python27>python mui_thread.py i am playing video: speed_and_crazy at Mon Jun 26 23:18:52 2017 all are over at Mon Jun 26 23:18:52 2017 i am playing music: chengdu at Mon Jun 26 23:18:52 2017 #从打印的时间可知,play_video、play_music和父进程几乎同时运行
从结果看,与我们最初的目标相差甚远,怎么没有按照顺序执行,为什么每个函数都只有一条日记输出?
那是因为子线程(play_video、play_music)和主线程print "all are over at %s \n"%ctime()都是同一时间启动,但由于主线程已经运行结束,所以导致子线程也同时终止,在这种条件下,我们如何保证子进程都能够执行完毕呢?
增加thread.join()并 放在循环外
from time import ctime,sleep import threading def play_video(video): for i in range(2): print "i am playing video: %s at %s \n"%(video,ctime()) sleep(1) def play_music(music): for i in range(2): print "i am playing music: %s at %s \n"%(music,ctime()) sleep(5) threads=[] thread1=threading.Thread(target=play_video,args=("speed_and_crazy",)) threads.append(thread1) thread2=threading.Thread(target=play_music,args=("chengdu",)) threads.append(thread2) if __name__=="__main__": for thread in threads: thread.setDaemon(True) thread.start() thread.join() #加在循环外, print "all are over at %s \n"%ctime()
运行结果:
1 C:\Python27>python mui_thread.py 2 i am playing video: speed_and_crazy at Mon Jun 26 23:32:21 2017 3 i am playing music: chengdu at Mon Jun 26 23:32:21 2017 4 5 6 i am playing video: speed_and_crazy at Mon Jun 26 23:32:22 2017 7 8 i am playing music: chengdu at Mon Jun 26 23:32:26 2017 9 10 all are over at Mon Jun 26 23:32:31 2017
thread.join()的作用是主线程必须等待子线程都执行完了才能结束,play_video、play_music几乎同时执行但是如果改变play_video、play_music里面的sleep的时长,即是下面的代码:
from time import ctime,sleep import threading def play_video(video): for i in range(2): print "i am playing video: %s at %s \n"%(video,ctime()) sleep(5) def play_music(music): for i in range(2): print "i am playing music: %s at %s \n"%(music,ctime()) sleep(1) threads=[] thread1=threading.Thread(target=play_video,args=("speed_and_crazy",)) threads.append(thread1) thread2=threading.Thread(target=play_music,args=("chengdu",)) threads.append(thread2) if __name__=="__main__": for thread in threads: thread.setDaemon(True) thread.start() thread.join() print "all are over at %s \n"%ctime()
此时运行结果:
C:\Python27>python mui_thread.py i am playing video: speed_and_crazy at Mon Jun 26 23:44:13 2017 i am playing music: chengdu at Mon Jun 26 23:44:13 2017 i am playing music: chengdu at Mon Jun 26 23:44:14 2017 all are over at Mon Jun 26 23:44:15 2017
我们看到play_video还有一条log没有打印出来,原因是thread.join()在循环外,此时的thread为play_music,父进程只会等待play_music进程执行完就结束,而不会等待play_video(sleep时间较长)执行完才结束,所以才会有上面的结果
时间: 2024-10-08 20:36:25