如何理解python的多线程编程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何理解python的多线程编程相关的知识,希望对你有一定的参考价值。

线程是程序员必须掌握的知识,多线程对于代码的并发执行、提升代码效率和运行都至关重要。今天就分享一个黑马程序员Python多线程编程的教程,从0开始学习python多任务编程,想了解python高并发实现,从基础到实践,通过知识点 + 案例教学法帮助你想你想迅速掌握python多任务。

课程内容:

1.掌握多任务实现的并行和并发

2.掌握多进程实现多任务

3.掌握多线程实现多任务

4.掌握合理搭配多进程和线程

适用人群:

1、对python多任务编程感兴趣的在校生及应届毕业生。

2、对目前职业有进一步提升要求,希望从事python人工智能行业高薪工作的在职人员。

3、对python人工智能行业感兴趣的相关人员。

基础课程主讲内容包括:

1.python多任务编程

基础班课程大纲:

00-课程介绍

01-多任务介绍

02-进程介绍

03-使用多进程来完成多任务

04-多进程执行带有参数的任务

05-获取进程的编号

06-进程注意点

07-案例-多进程实现传智视频文件夹多任务拷贝器

08-线程介绍

09-使用多线程执行多任务

10-线程执行带有参数的任务

11-主线程和子线程的结束顺序

12-线程之间的执行顺序是无序

13-线程和进程的对比

14-案例-多线程实现传智视频文件夹多任务拷贝器

15-课程总结

参考技术A 在 Python 中使用线程的实例和如何避免线程之间的竞争。 你应当将下边的例子运行多次,以便可以注意到线程是不可预测的和线程每次运行出的不同结果。声明:从这里开始忘掉你听到过的关于 GIL 的东西,因为 GIL 不会影响到我想要展示的东西。

Python的多线程编程

提到多线程,很多人就会望而却步,本文将由浅入深地带你攻克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_videoplay_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()在循环外,此时的threadplay_music,父进程只会等待play_music进程执行完就结束,而不会等待play_video(sleep时间较长)执行完才结束,所以才会有上面的结果

 



以上是关于如何理解python的多线程编程的主要内容,如果未能解决你的问题,请参考以下文章

python的多线程编程

Java 并发编程解析 | 如何正确理解Java领域中的多线程模型,主要用来解决什么问题?

python中的多线程和多进程编程

Python多线程编程详解

Java多线程,线程安全与不安全的理解,程序的多线程并发编程的基础概念,进程与线程的区别是什么

Java多线程,线程安全与不安全的理解,程序的多线程并发编程的基础概念,进程与线程的区别是什么