代码改变世界

Python---并发编程

2017-02-08 10:19  ZN23&24  阅读(104)  评论(0)    收藏  举报

进程是最小的资源单位,线程是最小的执行单位

一、进程                                                                                                                                                       

进程:就是一个程序在一个数据集上的一次动态执行过程。

进程由三部分组成:

1、程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成

2、数据集:数据集则是程序在执行过程中所需要使用的资源

3、进程控制块:进程控制块用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感

     知进程存在的唯一标志。

 

二、线程                                                                                                                                                            

   Threading用于提供线程相关的操作。线程是应用程序中工作的最小单元,它被包含在进程之中,是进程中的实际运作单位。一

条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

 

1、实现线程并发

 示例1:

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*- 
 3 #Author: nulige
 4 
 5 import threading  #线程
 6 import time
 7 
 8 def Hi(num): #有一个参数
 9     print("hello %s" %num)
10     time.sleep(3)  
11 
12 if __name__ == '__main__':
13 
14     t1=threading.Thread(target=Hi,args=(10,))  #创建了一个线程对象t1,10做为一个参数,传给num
15     t1.start()
16 
17     t2=threading.Thread(target=Hi,args=(9,))   #创建了一个线程对象t2,9做为一个参数,传给num
18     t2.start()
19 
20     print("ending.........")  #主线程输出ending
复制代码

执行结果:

1 hello 10    #子线程
2 hello 9     #子线程
3 ending.........   #主线程
4 #上面三个同时出来,再停顿三秒才结束
5 Process finished with exit code 0  #停顿3秒才结束

 

示例2:

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*- 
 3 #Author: nulige
 4 
 5 import threading
 6 import time
 7 
 8 def music():
 9     print("begin to listen %s"%time.ctime())
10     time.sleep(3)
11     print("stop to listen %s" %time.ctime())
12 
13 def game():
14     print("begin to play game %s"%time.ctime())
15     time.sleep(5)
16     print("stop to play game %s" %time.ctime())
17 
18 if __name__ == '__main__':
19 
20     t1=threading.Thread(target=music)
21     t1.start()
22     t2=threading.Thread(target=game)
23     t2.start()
复制代码

执行结果:

复制代码
1 #总共花了5秒时间
2 
3 begin to listen Sat Jan 14 12:34:43 2017
4 begin to play game Sat Jan 14 12:34:43 2017  #1、先打印2个
5 
6 stop to listen Sat Jan 14 12:34:46 2017      #2、等待3秒再打印一个
7 
8 stop to play game Sat Jan 14 12:34:48 2017   #3、再等待2秒,打印一个
复制代码

 

2、使用join方法

示例1:

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*- 
 3 #Author: nulige
 4 
 5 import threading
 6 import time
 7 
 8 def music():
 9     print("begin to listen %s"%time.ctime())
10     time.sleep(3)
11     print("stop to listen %s" %time.ctime())
12 
13 def game():
14     print("begin to play game %s"%time.ctime())
15     time.sleep(5)
16     print("stop to play game %s" %time.ctime())
17 
18 if __name__ == '__main__':
19 
20     t1=threading.Thread(target=music)
21     t2=threading.Thread(target=game)
22 
23     t1.start()  #运行实例的方法
24     t2.start()
25 
26     t1.join()   #子线程对象调用join()方法
27     t2.join()
28 
29     print("ending")  #在主线程中
复制代码

执行结果:

复制代码
begin to listen Sat Jan 14 12:58:34 2017
begin to play game Sat Jan 14 12:58:34 2017  #先打印2个

stop to listen Sat Jan 14 12:58:37 2017      #等待3秒,再打印一个

stop to play game Sat Jan 14 12:58:39 2017   #等待2秒,再打印两个
ending  
复制代码

 

示例2:

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*- 
 3 #Author: nulige
 4 
 5 import threading
 6 import time
 7 
 8 def music():
 9     print("begin to listen %s"%time.ctime())
10     time.sleep(3)
11     print("stop to listen %s" %time.ctime())
12 
13 def game():
14     print("begin to play game %s"%time.ctime())
15     time.sleep(5)
16     print("stop to play game %s" %time.ctime())
17 
18 if __name__ == '__main__':
19 
20     t1=threading.Thread(target=music)
21     t2=threading.Thread(target=game)
22 
23     t1.start()  #运行实例的方法
24     t2.start()
25 
26     t1.join()   #t1线程不结束,谁都不往下走
27 
28     print("ending")  
复制代码

执行结果:

复制代码
1 begin to listen Sat Jan 14 13:06:07 2017
2 begin to play game Sat Jan 14 13:06:07 2017  #先打印这两行
3 
4 stop to listen Sat Jan 14 13:06:10 2017      #再等待3秒打印这两行
5 ending
6 
7 stop to play game Sat Jan 14 13:06:12 2017   #再等待2秒打印这行
复制代码

 

示例3:

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*- 
 3 #Author: nulige
 4 
 5 import threading
 6 import time
 7 
 8 def music():
 9     print("begin to listen %s"%time.ctime())
10     time.sleep(3)
11     print("stop to listen %s" %time.ctime())
12 
13 def game():
14     print("begin to play game %s"%time.ctime())
15     time.sleep(5)
16     print("stop to play game %s" %time.ctime())
17 
18 if __name__ == '__main__':
19 
20     t1=threading.Thread(target=music)
21     t2=threading.Thread(target=game)
22 
23     t1.start()  #运行实例的方法
24     t2.start()
25 
26     t2.join()
27 
28     print("ending")  #在主线程中
复制代码

执行结果:

复制代码
1 begin to listen Sat Jan 14 13:12:34 2017     #先打印这两行
2 begin to play game Sat Jan 14 13:12:34 2017
3 
4 stop to listen Sat Jan 14 13:12:37 2017      #等待3秒,打印这一行
5 
6 stop to play game Sat Jan 14 13:12:39 2017   #等待2秒,打印这两行
7 ending
复制代码

 

示例4:并没有实现并发(失去多线程的意义)

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*- 
 3 #Author: nulige
 4 
 5 import threading
 6 import time
 7 
 8 def music():
 9     print("begin to listen %s"%time.ctime())
10     time.sleep(3)
11     print("stop to listen %s" %time.ctime())
12 
13 def game():
14     print("begin to play game %s"%time.ctime())
15     time.sleep(5)
16     print("stop to play game %s" %time.ctime())
17 
18 if __name__ == '__main__':
19 
20     t1=threading.Thread(target=music)
21     t2=threading.Thread(target=game)
22 
23     t1.start()
24 
25     t1.join()
26     t2.start()
27     
28     t2.join()
29 
30     print("ending")  #在主线程中
复制代码

执行结果:

复制代码
1 begin to listen Sat Jan 14 13:26:18 2017    #先打印条1行
2 
3 stop to listen Sat Jan 14 13:26:21 2017     #等待3秒再打印2行
4 begin to play game Sat Jan 14 13:26:21 2017
5 
6 stop to play game Sat Jan 14 13:26:26 2017  #等待5秒打印2行
7 ending
复制代码

 

三、线程的两种调用方式                                                                                                                                       

  threading 模块建立在 thread 模块之上。thread 模块以低级、原始的方式来处理和控制线程,而 threading 模块通过对 thread

进行二次封装,提供了更方便的 api 来处理线程。

1、直接调用(推荐写法)

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*- 
 3 #Author: nulige
 4 
 5 import threading
 6 import time
 7 
 8 
 9 def sayhi(num):  # 定义每个线程要运行的函数
10 
11     print("running on number:%s" % num)
12 
13     time.sleep(3)
14 
15 
16 if __name__ == '__main__':
17     t1 = threading.Thread(target=sayhi, args=(1,))  # 生成一个线程实例
18     t2 = threading.Thread(target=sayhi, args=(2,))  # 生成另一个线程实例
19 
20     t1.start()  # 启动线程
21     t2.start()  # 启动另一个线程
22 
23     print(t1.getName())  # 获取线程名
24     print(t2.getName())
复制代码

执行结果:

1 running on number:1
2 running on number:2
3 Thread-1
4 Thread-2

 

2、继承式调用(有些编程人员会用这种写法,也要能看懂。不推荐这种写法)

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*- 
 3 #Author: nulige
 4 
 5 import threading
 6 import time
 7 
 8 #自己定制一个MyThread的类
 9 class MyThread(threading.Thread):  
10     def __init__(self, num):
11         threading.Thread.__init__(self)
12         self.num = num
13 
14     def run(self):  # 定义每个线程要运行的函数
15 
16         print("running on number:%s" % self.num)
17 
18         time.sleep(3)
19 
20 
21 if __name__ == '__main__':
22     t1 = MyThread(1)  #继承这个类,把1这个参数,传给num ,t1就是个线程对象
23     t2 = MyThread(2)
24     t1.start()
25     t2.start()
26 
27     print("ending......")
复制代码

执行结果:

1 running on number:1
2 running on number:2
3 ending......

 

四、 threading.thread的实例方法                                                                                                                   

1、join&Daemon方法

示例1:没有用Daemon方法示例

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 #Author: nulige
 4 
 5 import threading
 6 from time import ctime,sleep
 7 import time
 8 
 9 def ListenMusic(name):
10 
11         print ("Begin listening to %s. %s" %(name,ctime()))
12         sleep(3)
13         print("end listening %s"%ctime())
14 
15 def RecordBlog(title):
16 
17         print ("Begin recording the %s! %s" %(title,ctime()))
18         sleep(5)
19         print('end recording %s'%ctime())
20 
21 #创建一个列表,把t1和t2加到列表中去
22 threads = []
23 t1 = threading.Thread(target=ListenMusic,args=('水手',))
24 t2 = threading.Thread(target=RecordBlog,args=('python线程',))
25 threads.append(t1)
26 threads.append(t2)
27 
28 if __name__ == '__main__':
29 
30     for t in threads:
31         t.start()
32 
33     print ("all over %s" %ctime())
复制代码

执行结果:

复制代码
1 Begin listening to 水手. Sat Jan 14 13:44:10 2017
2 Begin recording the python线程! Sat Jan 14 13:44:10 2017
3 all over Sat Jan 14 13:44:10 2017         #先打印三个出来; 主线程结束了
4 
5 end listening Sat Jan 14 13:44:13 2017    #等待3秒,打印这1个; 子线程还没有结束,会继续往下运行
6 
7 end recording Sat Jan 14 13:44:15 2017    #再等待2秒,打印这1个
复制代码

 

示例2: 用Daemon方法示例(设置t为守护线程,就是子线程,跟着主线程一起退出)

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 #Author: nulige
 4 
 5 import threading
 6 from time import ctime,sleep
 7 import time
 8 
 9 def ListenMusic(name):
10 
11         print ("Begin listening to %s. %s" %(name,ctime()))
12         sleep(3)
13         print("end listening %s"%ctime())
14 
15 def RecordBlog(title):
16 
17         print ("Begin recording the %s! %s" %(title,ctime()))
18         sleep(5)
19         print('end recording %s'%ctime())
20 
21 #创建一个列表,把t1和t2加到列表中去
22 threads = []
23 t1 = threading.Thread(target=ListenMusic,args=('水手',))
24 t2 = threading.Thread(target=RecordBlog,args=('python线程',))
25 threads.append(t1)
26 threads.append(t2)
27 
28 if __name__ == '__main__':
29 
30     for t in threads:
31         t.setDaemon(True) #设置t为守护线程; 注意:一定在start()之前设置,否则会报错
32 
33         t.start()
34 
35     print ("all over %s" %ctime())
复制代码

执行结果:

1 Begin listening to 水手. Sat Jan 14 13:51:30 2017    #三个同时打印出来
2 Begin recording the python线程! Sat Jan 14 13:51:30 2017
3 all over Sat Jan 14 13:51:30 2017

 

示例3:设置t1为守护线程,没有意义,达不到效果,因为t2还会继续执行

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 #Author: nulige
 4 
 5 import threading
 6 from time import ctime,sleep
 7 import time
 8 
 9 def ListenMusic(name):
10 
11         print ("Begin listening to %s. %s" %(name,ctime()))
12         sleep(3)
13         print("end listening %s"%ctime())
14 
15 def RecordBlog(title):
16 
17         print ("Begin recording the %s! %s" %(title,ctime()))
18         sleep(5)
19         print('end recording %s'%ctime())
20 
21 #创建一个列表,把t1和t2加到列表中去
22 threads = []
23 t1 = threading.Thread(target=ListenMusic,args=('水手',))
24 t2 = threading.Thread(target=RecordBlog,args=('python线程',))
25 threads.append(t1)
26 threads.append(t2)
27 
28 if __name__ == '__main__':
29 
30     t1.setDaemon(True)  #设置t1为守护线程; 注意:一定在start之前设置,否则会报错
31     for t in threads:
32 
33         t.start()
34 
35     print ("all over %s" %ctime())
复制代码

执行结果:

复制代码
1 Begin listening to 水手. Sat Jan 14 14:02:07 2017
2 Begin recording the python线程! Sat Jan 14 14:02:07 2017
3 all over Sat Jan 14 14:02:07 2017          #设置t1为守护线程,所以会先把这三条先打印出来
4 
5 end listening Sat Jan 14 14:02:10 2017     #再等待3秒打印t2,
6 
7 end recording Sat Jan 14 14:02:12 2017     #再等待3秒打印这条出来
复制代码

 

示例4:设置t2为守护线程,子线程才会跟着主线程一起退出

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 #Author: nulige
 4 
 5 import threading
 6 from time import ctime,sleep
 7 import time
 8 
 9 def ListenMusic(name):
10 
11         print ("Begin listening to %s. %s" %(name,ctime()))
12         sleep(3)
13         print("end listening %s"%ctime())
14 
15 def RecordBlog(title):
16 
17         print ("Begin recording the %s! %s" %(title,ctime()))
18         sleep(5)
19         print('end recording %s'%ctime())
20 
21 #创建一个列表,把t1和t2加到列表中去
22 threads = []
23 t1 = threading.Thread(target=ListenMusic,args=('水手',))
24 t2 = threading.Thread(target=RecordBlog,args=('python线程',))
25 threads.append(t1)
26 threads.append(t2)
27 
28 if __name__ == '__main__':
29 
30     t2.setDaemon(True)  # 设置t2为守护线程; 注意:一定在start之前设置,否则会报错
31     for t in threads:
32 
33         t.start()
34 
35     print ("all over %s" %ctime())
复制代码

执行结果:

1 Begin listening to 水手. Sat Jan 14 14:17:09 2017
2 Begin recording the python线程! Sat Jan 14 14:17:09 2017
3 all over Sat Jan 14 14:17:09 2017       #先打印这三条
4 
5 end listening Sat Jan 14 14:17:12 2017  #等待3秒,再打印这条;t1结束后,主线程也结束了。

 

2、一道面试题

复制代码
 1 #执行结果是什么?
 2 
 3 i = 0
 4 for i in range(10):
 5     i += 1
 6 print(i)
 7 
 8 执行结果:
 9 10
复制代码

 

3、其它方法

示例:getName()方法 (一般没什么用)

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 #Author: nulige
 4 
 5 import threading
 6 from time import ctime,sleep
 7 import time
 8 
 9 def ListenMusic(name):
10 
11         print ("Begin listening to %s. %s" %(name,ctime()))
12         sleep(3)
13         print("end listening %s"%ctime())
14 
15 def RecordBlog(title):
16 
17         print ("Begin recording the %s! %s" %(title,ctime()))
18         sleep(5)
19         print('end recording %s'%ctime())
20 
21 #创建一个列表,把t1和t2加到列表中去
22 threads = []
23 t1 = threading.Thread(target=ListenMusic,args=('水手',))
24 t2 = threading.Thread(target=RecordBlog,args=('python线程',))
25 threads.append(t1)
26 threads.append(t2)
27 
28 if __name__ == '__main__':
29 
30     t2.setDaemon(True)  # 设置t为守护进程; 注意:一定在start之前设置,否则会报错
31     for t in threads:
32         t.start()
33         print(t.getName())    #返回线程名称:Thread-1
34 
35     print ("all over %s" %ctime())
复制代码

执行结果:

复制代码
1 Begin listening to 水手. Sat Jan 14 14:36:44 2017
2 Thread-1   #返回线程名称
3 Begin recording the python线程! Sat Jan 14 14:36:44 2017
4 Thread-2   #返回默认的线程名称
5 all over Sat Jan 14 14:36:44 2017
6 end listening Sat Jan 14 14:36:47 2017
复制代码

 

 示例:threading.activeCount(),返回正在运行的线程数量

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 #Author: nulige
 4 
 5 import threading
 6 from time import ctime,sleep
 7 import time
 8 
 9 def ListenMusic(name):
10 
11         print ("Begin listening to %s. %s" %(name,ctime()))
12         sleep(3)
13         print("end listening %s"%ctime())
14 
15 def RecordBlog(title):
16 
17         print ("Begin recording the %s! %s" %(title,ctime()))
18         sleep(5)
19         print('end recording %s'%ctime())
20 
21 #创建一个列表,把t1和t2加到列表中去
22 threads = []
23 t1 = threading.Thread(target=ListenMusic,args=('水手',))
24 t2 = threading.Thread(target=RecordBlog,args=('python线程',))
25 threads.append(t1)
26 threads.append(t2)
27 
28 if __name__ == '__main__':
29 
30     t2.setDaemon(True)  #设置t为守护进程; 注意:一定在start之前设置,否则会报错
31     for t in threads:
32         t.start()
33 
34         print("count:", threading.active_count())   #判断有多少个线程的数量
35 
36     while threading.active_count()==1:  #等于1就相当于只有一个主线程,没有子线程
37 
38         print ("all over %s" %ctime())
复制代码

执行结果:

1 Begin listening to 水手. Sat Jan 14 14:49:00 2017
2 count: 2
3 Begin recording the python线程! Sat Jan 14 14:49:00 2017
4 count: 3  #得到的线程数量
5 end listening Sat Jan 14 14:49:03 2017