python3的多线程很多人无法理解是怎么运行的,因此本文从程序猿的日常生活出发,写了一个由浅入深的多线程教程,这样子大家就不会觉得陌生了,多线程真的很简单很简单!
不要讲多线程局限于库或者框架,自己造轮子才是最大的快乐。
-----------------------------------------以下是正文--------------------------------------------
假设我是一个程序猿,我想听歌,但是我又要打码,所以有:
我听完歌就去打码:
1 #!/usr/bin/python3.4
2 #-*- coding: utf-8 -*-
3
4 importtime5
6 defmatter1(music):7 print("我想听这些歌")8
9 for i inrange(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 defmatter2(number):18 print("我在打码")19
20 j =021 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 importtime5 importthreading6
7 defmatter1(music):8 print("我想听这些歌")9
10 for i inrange(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 defmatter2(number):19 print("我在打码")20
21 j =022 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 inthreads: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 importtime2 importthreading3
4 defmatter1(music):5 print("我想听这些歌")6
7 for i inrange(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 defmatter2(number):16 print("我在打码")17
18 j =019 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 inthreads: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 importtime5 importthreading6
7 classMyThread(threading.Thread):8 def __init__(self, func, args, name=''):9 threading.Thread.__init__(self)10 self.name =name11 self.func =func12 self.args =args13 #self.counter = counter
14
15 defrun(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 defmatter1(music):26 for i inrange(0,len(music)):27 print("第" + str(i + 1) + "首歌是:" +str(music[i]))28 #假设每一首歌曲的时间是2秒
29 time.sleep(2)30 print("切换下一首歌...")31
32 defmatter2(number):33 j =034 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 importtime5 importthreading6
7 classMyThread(threading.Thread):8 def __init__(self, func, args, name=''):9 threading.Thread.__init__(self)10 self.name =name11 self.func =func12 self.args =args13 #self.counter = counter
14
15 defrun(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 defmatter1(music):28 for i inrange(0,len(music)):29 print("第" + str(i + 1) + "首歌是:" +str(music[i]))30 #假设每一首歌曲的时间是2秒
31 time.sleep(2)32 print("切换下一首歌...")33
34 defmatter2(number):35 j =036 while j <=number:37 print("我准备写入第" + str(j + 1) +"行代码")38 j = j + 1
39 #假设每写一行代码的时间为1秒
40 time.sleep(1)41 print("写下一行代码...")42
43 defmatter3(snacks):44 for k inrange(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 importtime5 importthreading6
7 #打开线程锁
8 lock =threading.Lock()9
10 classMyThread(threading.Thread):11 def __init__(self, func, args, name=''):12 threading.Thread.__init__(self)13 self.name =name14 self.func =func15 self.args =args16 #self.counter = counter
17
18 defrun(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 defmatter1(music):31 for i inrange(0,len(music)):32 print("第" + str(i + 1) + "首歌是:" +str(music[i]))33 #假设每一首歌曲的时间是2秒
34 time.sleep(2)35 print("切换下一首歌...")36
37 defmatter2(number):38 lock.acquire()39 j =040 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 defmatter3(snacks):49 lock.acquire()50 for k inrange(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首歌是:music13 打码线程开始了##################
4 我准备写入第1行代码5 零食线程开始了##################
6 写下一行代码...7 我准备写入第2行代码8 写下一行代码...9 我准备写入第3行代码10 写下一行代码...11 我准备写入第4行代码12 写下一行代码...13 我准备写入第5行代码14 写下一行代码...15 打码线程结束了##################
16 我正在听着歌吃咪咪零食17 切换下一首歌...18 第2首歌是:music219 吃完了一包零食20 我正在听着歌吃辣条零食21 吃完了一包零食22 零食线程结束了##################
23 切换下一首歌...24 第3首歌是:music325 切换下一首歌...26 听歌线程结束了##################
perfect!