个人博客转至:tybai.com

无聊就想打码,打码使我快乐


Fork me on GitHub

python3多线程趣味详解

python3的多线程很多人无法理解是怎么运行的,因此本文从程序猿的日常生活出发,写了一个由浅入深的多线程教程,这样子大家就不会觉得陌生了,多线程真的很简单很简单!

 不要讲多线程局限于库或者框架,自己造轮子才是最大的快乐。

-----------------------------------------以下是正文--------------------------------------------

假设我是一个程序猿,我想听歌,但是我又要打码,所以有:

我听完歌就去打码:

 1 #!/usr/bin/python3.4
 2 # -*- coding: utf-8 -*-
 3 
 4 import time
 5 
 6 def matter1(music):
 7     print("我想听这些歌")
 8 
 9     for i in range(0,len(music)):
10         print("" + str(i + 1) + "首歌是:" + str(music[i]))
11         # 当前时间为
12         print(time.strftime('%Y%H%M%S', time.localtime()))
13         # 假设每一首歌曲的时间是2秒
14         time.sleep(2)
15         print("切换下一首歌...")
16 
17 def matter2(number):
18     print("我在打码")
19 
20     j = 0
21     while j <= number:
22         print("我准备写入第" + str(j + 1) +"行代码")
23         j = j + 1
24         # 当前时间为
25         print(time.strftime('%Y%H%M%S', time.localtime()))
26         # 假设每写一行代码的时间为1秒
27         time.sleep(1)
28         print("写下一行代码...")
29 
30 if __name__ == '__main__':
31 
32     start = time.time()
33 
34     # 设定我要听的歌为
35     music = ["music1","music2","music3"]
36     # 开始听歌
37     matter1(music)
38     # 设定我要打码的行数
39     number = 5
40     # 开始打码
41     matter2(number)
42 
43     end = time.time()
44     print("完成的时间为:" + str(end - start))

记录来的完成时间为:

完成的时间为:12.007483959197998

时间上完全符合,但是身为一个程序猿,可以一边打码一边听歌,那么设计一个多线程,让他们同时进行:

 1 #!/usr/bin/python3.4
 2 # -*- coding: utf-8 -*-
 3 
 4 import time
 5 import threading
 6 
 7 def matter1(music):
 8     print("我想听这些歌")
 9 
10     for i in range(0,len(music)):
11         print("" + str(i + 1) + "首歌是:" + str(music[i]))
12         # 当前时间为
13         print(time.strftime('%Y%H%M%S', time.localtime()))
14         # 假设每一首歌曲的时间是2秒
15         time.sleep(2)
16         print("切换下一首歌...")
17 
18 def matter2(number):
19     print("我在打码")
20 
21     j = 0
22     while j <= number:
23         print("我准备写入第" + str(j + 1) +"行代码")
24         j = j + 1
25         # 当前时间为
26         print(time.strftime('%Y%H%M%S', time.localtime()))
27         # 假设每写一行代码的时间为1秒
28         time.sleep(1)
29         print("写下一行代码...")
30 
31 if __name__ == '__main__':
32     # 设定我要听的歌为
33     music = ["music1","music2","music3"]
34 
35     # 设定我要打码的行数
36     number = 5
37     # 建立一个新数组
38     threads = []
39     # 将听歌放入数组里面
40     thing1 = threading.Thread(target=matter1, args=(music,))
41     threads.append(thing1)
42     # 将打码放入数组里面
43     thing2 = threading.Thread(target=matter2, args=(number,))
44     threads.append(thing2)
45 
46     # 开始时间
47     start = time.time()
48     # 写个for让两件事情都进行
49     for thing in threads:
50         # setDaemon为主线程启动了线程matter1和matter2
51         # 启动也就是相当于执行了这个for循环
52         thing.setDaemon(True)
53         thing.start()
54 
55     # 结束时间
56     end = time.time()
57     print("完成的时间为:" + str(end - start))

但是直接就结束了?

完成的时间为:0.0010008811950683594

原来是setDaemon,主线程启动两个子线程后做事后,主线程就不管子线程是否运行完毕,直接往下运行,直接运行到

print("完成的时间为:" + str(end - start))

然后程序就结束了,因此,为了防止子线程还没结束主线程就结束的意外情况,在程序里面加个join:

 1 import time
 2 import threading
 3 
 4 def matter1(music):
 5     print("我想听这些歌")
 6 
 7     for i in range(0,len(music)):
 8         print("" + str(i + 1) + "首歌是:" + str(music[i]))
 9         # 当前时间为
10         print(time.strftime('%Y%H%M%S', time.localtime()))
11         # 假设每一首歌曲的时间是2秒
12         time.sleep(2)
13         print("切换下一首歌...")
14 
15 def matter2(number):
16     print("我在打码")
17 
18     j = 0
19     while j <= number:
20         print("我准备写入第" + str(j + 1) +"行代码")
21         j = j + 1
22         # 当前时间为
23         print(time.strftime('%Y%H%M%S', time.localtime()))
24         # 假设每写一行代码的时间为1秒
25         time.sleep(1)
26         print("写下一行代码...")
27 
28 if __name__ == '__main__':
29     # 设定我要听的歌为
30     music = ["music1","music2","music3"]
31 
32     # 设定我要打码的行数
33     number = 5
34     # 建立一个新数组
35     threads = []
36     # 将听歌放入数组里面
37     thing1 = threading.Thread(target=matter1, args=(music,))
38     threads.append(thing1)
39     # 将打码放入数组里面
40     thing2 = threading.Thread(target=matter2, args=(number,))
41     threads.append(thing2)
42 
43     # 开始时间
44     start = time.time()
45     # 写个for让两件事情都进行
46     for thing in threads:
47         # setDaemon为主线程启动了线程matter1和matter2
48         # 启动也就是相当于执行了这个for循环
49         thing.setDaemon(True)
50         thing.start()
51 
52     # 子线程没结束前主线程会被卡在这里
53     thing1.join()
54     thing2.join()
55     # 结束时间
56     end = time.time()
57     print("完成的时间为:" + str(end - start))

 

最后运行的时间就是打码的时间:

完成的时间为:6.003339052200317

这就真正做到了一边听歌一边打码的双手互博的状态,本文后面的那0.003333秒就别纠结了,系统运行程序花个0.0033333秒不过分吧

偷懒打码打4行:

number = 4
完成的时间为:5.008083820343018

------------------------------我是快乐的分割线------------------------------

网上的多线程都是写成“类”的形式,这里写成函数不符合“大众”标准,那么就改成类的形式:

 1 #!/usr/bin/python3.4
 2 # -*- coding: utf-8 -*-
 3 
 4 import time
 5 import threading
 6 
 7 class MyThread(threading.Thread):
 8     def __init__(self, func, args, name=''):
 9         threading.Thread.__init__(self)
10         self.name = name
11         self.func = func
12         self.args = args
13         #self.counter = counter
14 
15     def run(self):
16         # 某某线程要开始了
17         print(self.name + "开始了##################")
18 
19         if self.name == "听歌线程":
20             matter1(music)
21         elif self.name == "打码线程":
22             matter2(number)
23         print(self.name + "结束了##################")
24 
25 def matter1(music):
26     for i in range(0,len(music)):
27         print("" + str(i + 1) + "首歌是:" + str(music[i]))
28         # 假设每一首歌曲的时间是2秒
29         time.sleep(2)
30         print("切换下一首歌...")
31 
32 def matter2(number):
33     j = 0
34     while j <= number:
35         print("我准备写入第" + str(j + 1) +"行代码")
36         j = j + 1
37         # 假设每写一行代码的时间为1秒
38         time.sleep(1)
39         print("写下一行代码...")
40 
41 
42 if __name__ == '__main__':
43     # 设定我要听的歌为
44     music = ["music1","music2","music3"]
45 
46     # 设定我要打码的行数
47     number = 4
48 
49     # 开始时间
50     start = time.time()
51 
52     thing1 = MyThread(matter1, music,"听歌线程")
53     thing2 = MyThread(matter2, number, "打码线程")
54     thing1.start()
55     thing2.start()
56     thing1.join()
57     thing2.join()
58 
59     # 结束时间
60     end = time.time()
61     print("完成的时间为:" + str(end - start))

运行结果也是6秒:

完成的时间为:6.001942157745361

----------------------我是快乐的分割线-------------------------

程序猿在跑代码的时候是很无聊的,无聊的时候就会想到去吃零食,那么我就加入一个函数:

 1 #!/usr/bin/python3.4
 2 # -*- coding: utf-8 -*-
 3 
 4 import time
 5 import threading
 6 
 7 class MyThread(threading.Thread):
 8     def __init__(self, func, args, name=''):
 9         threading.Thread.__init__(self)
10         self.name = name
11         self.func = func
12         self.args = args
13         #self.counter = counter
14 
15     def run(self):
16         # 某某线程要开始了
17         print(self.name + "开始了##################")
18 
19         if self.name == "听歌线程":
20             matter1(music)
21         elif self.name == "打码线程":
22             matter2(number)
23         elif self.name == "零食线程":
24             matter3(snacks)
25         print(self.name + "结束了##################")
26 
27 def matter1(music):
28     for i in range(0,len(music)):
29         print("" + str(i + 1) + "首歌是:" + str(music[i]))
30         # 假设每一首歌曲的时间是2秒
31         time.sleep(2)
32         print("切换下一首歌...")
33 
34 def matter2(number):
35     j = 0
36     while j <= number:
37         print("我准备写入第" + str(j + 1) +"行代码")
38         j = j + 1
39         # 假设每写一行代码的时间为1秒
40         time.sleep(1)
41         print("写下一行代码...")
42 
43 def matter3(snacks):
44     for k in range(0,len(snacks)):
45         print("我正在听着歌吃" + str(snacks[k]) + "零食")
46         #每吃一袋零食间隔5秒
47         time.sleep(5)
48         print("吃完了一包零食")
49 
50 if __name__ == '__main__':
51     # 设定我要听的歌为
52     music = ["music1","music2","music3"]
53 
54     # 设定我要打码的行数
55     number = 4
56 
57     # 设定我想吃的零食
58     snacks = ["咪咪","辣条"]
59 
60     # 开始时间
61     start = time.time()
62 
63     thing1 = MyThread(matter1, music,"听歌线程")
64     thing2 = MyThread(matter2, number, "打码线程")
65     thing3 = MyThread(matter3, snacks, "零食线程")
66     thing1.start()
67     thing2.start()
68     thing3.start()
69     thing1.join()
70     thing2.join()
71     thing3.join()
72 
73     # 结束时间
74     end = time.time()
75     print("完成的时间为:" + str(end - start))

程序运行的时间是:

完成的时间为:10.000968933105469

感觉还是吃零食比较耗时间。但是但是,程序猿只有两个手,那么吃零食和打码是不能同时进行了,那么这里加个线程锁:

 1 #!/usr/bin/python3.4
 2 # -*- coding: utf-8 -*-
 3 
 4 import time
 5 import threading
 6 
 7 # 打开线程锁
 8 lock = threading.Lock()
 9 
10 class MyThread(threading.Thread):
11     def __init__(self, func, args, name=''):
12         threading.Thread.__init__(self)
13         self.name = name
14         self.func = func
15         self.args = args
16         #self.counter = counter
17 
18     def run(self):
19         # 某某线程要开始了
20         print(self.name + "开始了##################")
21 
22         if self.name == "听歌线程":
23             matter1(music)
24         elif self.name == "打码线程":
25             matter2(number)
26         elif self.name == "零食线程":
27             matter3(snacks)
28         print(self.name + "结束了##################")
29 
30 def matter1(music):
31     for i in range(0,len(music)):
32         print("" + str(i + 1) + "首歌是:" + str(music[i]))
33         # 假设每一首歌曲的时间是2秒
34         time.sleep(2)
35         print("切换下一首歌...")
36 
37 def matter2(number):
38     lock.acquire()
39     j = 0
40     while j <= number:
41         print("我准备写入第" + str(j + 1) +"行代码")
42         j = j + 1
43         # 假设每写一行代码的时间为1秒
44         time.sleep(1)
45         print("写下一行代码...")
46     lock.release()
47 
48 def matter3(snacks):
49     lock.acquire()
50     for k in range(0,len(snacks)):
51         print("我正在听着歌吃" + str(snacks[k]) + "零食")
52         #每吃一袋零食间隔5秒
53         time.sleep(5)
54         print("吃完了一包零食")
55     lock.release()
56 
57 if __name__ == '__main__':
58     # 设定我要听的歌为
59     music = ["music1","music2","music3"]
60 
61     # 设定我要打码的行数
62     number = 4
63 
64     # 设定我想吃的零食
65     snacks = ["咪咪","辣条"]
66 
67     # 开始时间
68     start = time.time()
69 
70     thing1 = MyThread(matter1, music,"听歌线程")
71     thing2 = MyThread(matter2, number, "打码线程")
72     thing3 = MyThread(matter3, snacks, "零食线程")
73     thing1.start()
74     thing2.start()
75     thing3.start()
76     thing1.join()
77     thing2.join()
78     thing3.join()
79 
80     # 结束时间
81     end = time.time()
82     print("完成的时间为:" + str(end - start))

运行时间为:

完成的时间为:15.001857995986938

这里解释一下:

只是听歌和打码花的时间是5s多;

听歌、打码、吃零食同时进行是10s多;

加了线程锁后,打码和吃零食不能同时进行,那么就变成:

听歌和打码花的时间是5s多;

单独吃零食是10s多,加起来就是15秒;

为了验证吃零食的时候还是听着歌的,所以将听歌的时间间隔改成10s,得到的运行时间为:

完成的时间为:30.000711917877197

运行结果贴出来看一下:

 1 听歌线程开始了##################
 2 第1首歌是:music1
 3 打码线程开始了##################
 4 我准备写入第1行代码
 5 零食线程开始了##################
 6 写下一行代码...
 7 我准备写入第2行代码
 8 写下一行代码...
 9 我准备写入第3行代码
10 写下一行代码...
11 我准备写入第4行代码
12 写下一行代码...
13 我准备写入第5行代码
14 写下一行代码...
15 打码线程结束了##################
16 我正在听着歌吃咪咪零食
17 切换下一首歌...
18 第2首歌是:music2
19 吃完了一包零食
20 我正在听着歌吃辣条零食
21 吃完了一包零食
22 零食线程结束了##################
23 切换下一首歌...
24 第3首歌是:music3
25 切换下一首歌...
26 听歌线程结束了##################

perfect!

posted on 2016-09-06 19:34 TTyb 阅读(...) 评论(...) 编辑 收藏

导航


不用多久

我就会升职加薪

当上总经理

出任CEO

迎娶白富美

走上人生巅峰

Pulpit rock