python趣味详解多线程

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 #!/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     thing.join()
57     # 结束时间
58     end = time.time()
59     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!

转载请注明出处:https://i.cnblogs.com/EditPosts.aspx?postid=5846745

时间: 2024-10-10 15:14:36

python趣味详解多线程的相关文章

python线程详解

#线程状态 #线程同步(锁)#多线程的优势在于可以同时运行多个任务,至少感觉起来是这样,但是当线程需要共享数据时,可能存在数据不同步的问题. #threading模块#常用方法:'''threading.currentThread():返回当前的线程变量threading.enumerate():返回一个包含正在运行的线程的list,正在运行指:线程启动后,结束前,不包含启动前和终止后的线程threading.activeCount():返回正在运行的线程数量,与len(threading.en

python正则表达式详解

python正则表达式详解 正则表达式是一个很强大的字符串处理工具,几乎任何关于字符串的操作都可以使用正则表达式来完成,作为一个爬虫工作者,每天和字符串打交道,正则表达式更是不可或缺的技能,正则表达式的在不同的语言中使用方式可能不一样,不过只要学会了任意一门语言的正则表达式用法,其他语言中大部分也只是换了个函数的名称而已,本质都是一样的.下面,我来介绍一下python中的正则表达式是怎么使用的. 首先,python中的正则表达式大致分为以下几部分: 元字符 模式 函数 re 内置对象用法 分组用

python difflib详解

difflib -帮助进行差异化比较 这个模块提供的类和方法用来进行差异化比较,它能够生成文本或者html格式的差异化比较结果,如果需要比较目录的不同,可以使用filecmp模块. class difflib.SequenceMatcher 这是可以用来比较任何类型片段的类,只要比较的片段是可hash的,都可以用来比较,使用非常灵活.他源于1980,s的“完形匹配算法”,并且进行了一系列的优化和改进. 通过对算法的复杂度比较,它由于原始的完形匹配算法,在最坏情况下有n的平方次运算,在最好情况下,

详解多线程MT和多线程MD的区别

这段时间司在招实习生,而不管是远程的电话面试或者是实际现场面试中领导都喜欢问你这个问题,但是可惜的是能很好答上来的人很少.后来发现不管是应届的实习生,甚至有些实际参加工作几年的人也未必真的了解这个问题.今天想写一篇详解,希望对广大程序员有一定的帮助. 区别1:全局堆句柄不一样. 网上有一个说法,就是一个线程一个栈,一个模块一个堆.前者很容易有理解,每个线程创建的时候在CreateThread中都能制定默认栈大小,只是很多情况下都取了默认值.而一个模块一个堆呢?其实很简单测试,如果是一个多线程MT

转 python数据类型详解

python数据类型详解 目录 1.字符串 2.布尔类型 3.整数 4.浮点数 5.数字 6.列表 7.元组 8.字典 9.日期 1.字符串 1.1.如何在Python中使用字符串 a.使用单引号(') 用单引号括起来表示字符串,例如: str='this is string'; print str; b.使用双引号(") 双引号中的字符串与单引号中的字符串用法完全相同,例如: str="this is string"; print str; c.使用三引号(''') 利用三

Python列表详解

Python列表详解: 创建一个列表,只要把逗号分隔的不同数据项使用方括号括起来即可. 比如:    list = [1, 2, 3, 4, 5 ]; 与字符串的索引一样,列表索引从0开始. Python列表函数即方法: Python所包含的函数: 1.cmp() 描述: cmp()用于比较两个列表的元素. 语法: cmp (list1,list2) 返回值: 如果比较的元素是同类型的,则比较其值,返回结果. 如果两个元素不是同一种类型,则检查它们是否是数字. 如果是数字,执行必要的数字强制类型

Python 递归函数 详解

Python 递归函数 详解   在函数内调用当前函数本身的函数就是递归函数   下面是一个递归函数的实例: 第一次接触递归函数的人,都会被它调用本身而搞得晕头转向,而且看上面的函数调用,得到的结果会是: 为什么会得出上面的结果呢?因为都把调用函数本身之后的代码给忘记了,就是else之后的python 代码. 实际此递归函数输出的是以下结果: 相信大家看到这里都有点蒙,小编也一样,我第一次看到这个递归函数时,只能理解到第一个结果.那是因为,大部分人在做事情的时候,中断第一件事,被安排去做第二件事

进行概念详解 多线程上篇(二)

操作系统是程序与硬件交互的中间层,现代操作系统将程序的一次执行抽象为进程和线程的概念. 进程作为资源分配的基本单位,线程作为执行的基本单位. 进程和线程其实就是操作系统程序本身实现控制一个程序运行的数据项描述 所有的程序都是面向语言进行开发的,而语言本身是面向操作系统的,线程是操作系统对程序一次运行的抽象 所以,所有的多线程编程模型,必然遵从操作系统的大逻辑,必然是符合操作系统的对线程的抽象概念,操作系统在抽象之上提供了API供应用程序调用 简言之,应用程序的底层是借助于操作系统来完成多线程编程

Python数据类型详解——列表

Python数据类型详解--列表 在"Python之基本数据类型概览"一节中,大概介绍了列表的基本用法,本节我们详细学一下列表. 如何定义列表:在[]内以英文里输入法的逗号,,按照索引,存放各种数据类型,每个位置代表一个元素. 回顾一下列表的特点: 1.可存放多个值. 2.按照从左到右的顺序定义列表元素,下标从0开始顺序访问,是有序的. 3.可修改指定索引位置对应的值,可变. 一.列表元素的增加操作 1.追加 用append方法将数据追加到列表的尾部 names = ['Kwan',