python3多线程趣味详解
python3的多线程很多人无法理解是怎么运行的,因此本文从程序猿的日常生活出发,写了一个由浅入深的多线程教程,这样子大家就不会觉得陌生了,多线程真的很简单很简单!
不要讲多线程局限于库或者框架,自己造轮子才是最大的快乐。
-----------------------------------------以下是正文--------------------------------------------
假设我是一个程序猿,我想听歌,但是我又要打码,所以有:
我听完歌就去打码:
#!/usr/bin/python3.4
# -*- coding: utf-8 -*- import time def matter1(music):
print("我想听这些歌") for i in range(0,len(music)):
print("第" + str(i + 1) + "首歌是:" + str(music[i]))
# 当前时间为
print(time.strftime('%Y%H%M%S', time.localtime()))
# 假设每一首歌曲的时间是2秒
time.sleep(2)
print("切换下一首歌...") def matter2(number):
print("我在打码") j = 0
while j <= number:
print("我准备写入第" + str(j + 1) +"行代码")
j = j + 1
# 当前时间为
print(time.strftime('%Y%H%M%S', time.localtime()))
# 假设每写一行代码的时间为1秒
time.sleep(1)
print("写下一行代码...") if __name__ == '__main__': start = time.time() # 设定我要听的歌为
music = ["music1","music2","music3"]
# 开始听歌
matter1(music)
# 设定我要打码的行数
number = 5
# 开始打码
matter2(number) end = time.time()
print("完成的时间为:" + str(end - start))
记录来的完成时间为:
完成的时间为:12.007483959197998
时间上完全符合,但是身为一个程序猿,可以一边打码一边听歌,那么设计一个多线程,让他们同时进行:
#!/usr/bin/python3.4
# -*- coding: utf-8 -*- import time
import threading def matter1(music):
print("我想听这些歌") for i in range(0,len(music)):
print("第" + str(i + 1) + "首歌是:" + str(music[i]))
# 当前时间为
print(time.strftime('%Y%H%M%S', time.localtime()))
# 假设每一首歌曲的时间是2秒
time.sleep(2)
print("切换下一首歌...") def matter2(number):
print("我在打码") j = 0
while j <= number:
print("我准备写入第" + str(j + 1) +"行代码")
j = j + 1
# 当前时间为
print(time.strftime('%Y%H%M%S', time.localtime()))
# 假设每写一行代码的时间为1秒
time.sleep(1)
print("写下一行代码...") if __name__ == '__main__':
# 设定我要听的歌为
music = ["music1","music2","music3"] # 设定我要打码的行数
number = 5
# 建立一个新数组
threads = []
# 将听歌放入数组里面
thing1 = threading.Thread(target=matter1, args=(music,))
threads.append(thing1)
# 将打码放入数组里面
thing2 = threading.Thread(target=matter2, args=(number,))
threads.append(thing2) # 开始时间
start = time.time()
# 写个for让两件事情都进行
for thing in threads:
# setDaemon为主线程启动了线程matter1和matter2
# 启动也就是相当于执行了这个for循环
thing.setDaemon(True)
thing.start() # 结束时间
end = time.time()
print("完成的时间为:" + str(end - start))
但是直接就结束了?
完成的时间为:0.0010008811950683594
原来是setDaemon,主线程启动两个子线程后做事后,主线程就不管子线程是否运行完毕,直接往下运行,直接运行到
print("完成的时间为:" + str(end - start))
然后程序就结束了,因此,为了防止子线程还没结束主线程就结束的意外情况,在程序里面加个join:
import time
import threading def matter1(music):
print("我想听这些歌") for i in range(0,len(music)):
print("第" + str(i + 1) + "首歌是:" + str(music[i]))
# 当前时间为
print(time.strftime('%Y%H%M%S', time.localtime()))
# 假设每一首歌曲的时间是2秒
time.sleep(2)
print("切换下一首歌...") def matter2(number):
print("我在打码") j = 0
while j <= number:
print("我准备写入第" + str(j + 1) +"行代码")
j = j + 1
# 当前时间为
print(time.strftime('%Y%H%M%S', time.localtime()))
# 假设每写一行代码的时间为1秒
time.sleep(1)
print("写下一行代码...") if __name__ == '__main__':
# 设定我要听的歌为
music = ["music1","music2","music3"] # 设定我要打码的行数
number = 5
# 建立一个新数组
threads = []
# 将听歌放入数组里面
thing1 = threading.Thread(target=matter1, args=(music,))
threads.append(thing1)
# 将打码放入数组里面
thing2 = threading.Thread(target=matter2, args=(number,))
threads.append(thing2) # 开始时间
start = time.time()
# 写个for让两件事情都进行
for thing in threads:
# setDaemon为主线程启动了线程matter1和matter2
# 启动也就是相当于执行了这个for循环
thing.setDaemon(True)
thing.start() # 子线程没结束前主线程会被卡在这里
thing1.join()
thing2.join()
# 结束时间
end = time.time()
print("完成的时间为:" + str(end - start))
最后运行的时间就是打码的时间:
完成的时间为:6.003339052200317
这就真正做到了一边听歌一边打码的双手互博的状态,本文后面的那0.003333秒就别纠结了,系统运行程序花个0.0033333秒不过分吧
偷懒打码打4行:
number = 4
完成的时间为:5.008083820343018
------------------------------我是快乐的分割线------------------------------
网上的多线程都是写成“类”的形式,这里写成函数不符合“大众”标准,那么就改成类的形式:
#!/usr/bin/python3.4
# -*- coding: utf-8 -*- import time
import threading class MyThread(threading.Thread):
def __init__(self, func, args, name=''):
threading.Thread.__init__(self)
self.name = name
self.func = func
self.args = args
#self.counter = counter def run(self):
# 某某线程要开始了
print(self.name + "开始了##################") if self.name == "听歌线程":
matter1(music)
elif self.name == "打码线程":
matter2(number)
print(self.name + "结束了##################") def matter1(music):
for i in range(0,len(music)):
print("第" + str(i + 1) + "首歌是:" + str(music[i]))
# 假设每一首歌曲的时间是2秒
time.sleep(2)
print("切换下一首歌...") def matter2(number):
j = 0
while j <= number:
print("我准备写入第" + str(j + 1) +"行代码")
j = j + 1
# 假设每写一行代码的时间为1秒
time.sleep(1)
print("写下一行代码...") if __name__ == '__main__':
# 设定我要听的歌为
music = ["music1","music2","music3"] # 设定我要打码的行数
number = 4 # 开始时间
start = time.time() thing1 = MyThread(matter1, music,"听歌线程")
thing2 = MyThread(matter2, number, "打码线程")
thing1.start()
thing2.start()
thing1.join()
thing2.join() # 结束时间
end = time.time()
print("完成的时间为:" + str(end - start))
运行结果也是6秒:
完成的时间为:6.001942157745361
----------------------我是快乐的分割线-------------------------
程序猿在跑代码的时候是很无聊的,无聊的时候就会想到去吃零食,那么我就加入一个函数:
#!/usr/bin/python3.4
# -*- coding: utf-8 -*- import time
import threading class MyThread(threading.Thread):
def __init__(self, func, args, name=''):
threading.Thread.__init__(self)
self.name = name
self.func = func
self.args = args
#self.counter = counter def run(self):
# 某某线程要开始了
print(self.name + "开始了##################") if self.name == "听歌线程":
matter1(music)
elif self.name == "打码线程":
matter2(number)
elif self.name == "零食线程":
matter3(snacks)
print(self.name + "结束了##################") def matter1(music):
for i in range(0,len(music)):
print("第" + str(i + 1) + "首歌是:" + str(music[i]))
# 假设每一首歌曲的时间是2秒
time.sleep(2)
print("切换下一首歌...") def matter2(number):
j = 0
while j <= number:
print("我准备写入第" + str(j + 1) +"行代码")
j = j + 1
# 假设每写一行代码的时间为1秒
time.sleep(1)
print("写下一行代码...") def matter3(snacks):
for k in range(0,len(snacks)):
print("我正在听着歌吃" + str(snacks[k]) + "零食")
#每吃一袋零食间隔5秒
time.sleep(5)
print("吃完了一包零食") if __name__ == '__main__':
# 设定我要听的歌为
music = ["music1","music2","music3"] # 设定我要打码的行数
number = 4 # 设定我想吃的零食
snacks = ["咪咪","辣条"] # 开始时间
start = time.time() thing1 = MyThread(matter1, music,"听歌线程")
thing2 = MyThread(matter2, number, "打码线程")
thing3 = MyThread(matter3, snacks, "零食线程")
thing1.start()
thing2.start()
thing3.start()
thing1.join()
thing2.join()
thing3.join() # 结束时间
end = time.time()
print("完成的时间为:" + str(end - start))
程序运行的时间是:
完成的时间为:10.000968933105469
感觉还是吃零食比较耗时间。但是但是,程序猿只有两个手,那么吃零食和打码是不能同时进行了,那么这里加个线程锁:
#!/usr/bin/python3.4
# -*- coding: utf-8 -*- import time
import threading # 打开线程锁
lock = threading.Lock() class MyThread(threading.Thread):
def __init__(self, func, args, name=''):
threading.Thread.__init__(self)
self.name = name
self.func = func
self.args = args
#self.counter = counter def run(self):
# 某某线程要开始了
print(self.name + "开始了##################") if self.name == "听歌线程":
matter1(music)
elif self.name == "打码线程":
matter2(number)
elif self.name == "零食线程":
matter3(snacks)
print(self.name + "结束了##################") def matter1(music):
for i in range(0,len(music)):
print("第" + str(i + 1) + "首歌是:" + str(music[i]))
# 假设每一首歌曲的时间是2秒
time.sleep(2)
print("切换下一首歌...") def matter2(number):
lock.acquire()
j = 0
while j <= number:
print("我准备写入第" + str(j + 1) +"行代码")
j = j + 1
# 假设每写一行代码的时间为1秒
time.sleep(1)
print("写下一行代码...")
lock.release() def matter3(snacks):
lock.acquire()
for k in range(0,len(snacks)):
print("我正在听着歌吃" + str(snacks[k]) + "零食")
#每吃一袋零食间隔5秒
time.sleep(5)
print("吃完了一包零食")
lock.release() if __name__ == '__main__':
# 设定我要听的歌为
music = ["music1","music2","music3"] # 设定我要打码的行数
number = 4 # 设定我想吃的零食
snacks = ["咪咪","辣条"] # 开始时间
start = time.time() thing1 = MyThread(matter1, music,"听歌线程")
thing2 = MyThread(matter2, number, "打码线程")
thing3 = MyThread(matter3, snacks, "零食线程")
thing1.start()
thing2.start()
thing3.start()
thing1.join()
thing2.join()
thing3.join() # 结束时间
end = time.time()
print("完成的时间为:" + str(end - start))
运行时间为:
完成的时间为:15.001857995986938
这里解释一下:
只是听歌和打码花的时间是5s多; 听歌、打码、吃零食同时进行是10s多;
加了线程锁后,打码和吃零食不能同时进行,那么就变成:
听歌和打码花的时间是5s多; 单独吃零食是10s多,加起来就是15秒;
为了验证吃零食的时候还是听着歌的,所以将听歌的时间间隔改成10s,得到的运行时间为:
完成的时间为:30.000711917877197
运行结果贴出来看一下:
听歌线程开始了##################
第1首歌是:music1
打码线程开始了##################
我准备写入第1行代码
零食线程开始了##################
写下一行代码...
我准备写入第2行代码
写下一行代码...
我准备写入第3行代码
写下一行代码...
我准备写入第4行代码
写下一行代码...
我准备写入第5行代码
写下一行代码...
打码线程结束了##################
我正在听着歌吃咪咪零食
切换下一首歌...
第2首歌是:music2
吃完了一包零食
我正在听着歌吃辣条零食
吃完了一包零食
零食线程结束了##################
切换下一首歌...
第3首歌是:music3
切换下一首歌...
听歌线程结束了##################
perfect!
python3多线程趣味详解的更多相关文章
- python3多线程应用详解(第四卷:图解多线程中LOCK)
先来看下图形对比: 发现没有这种密集型计算的任务中,多线程没有穿行的速率快,原因就是多线程在线程切换间也是要耗时的而密集型计算任务执行时几乎没以偶IO阻塞,这样你说谁快
- python3多线程应用详解(第二卷:多线程到底是怎么工作的)
现在很多人都说用多线程工作快是因为多个不同任务可以同时执行,注意我说的是不同任务,要是重复做一件事达到相同效果就是画蛇添足了,其实这是个错误的说法,线程真正的本质是无法同时执行的.现在我们来看下多线程 ...
- python3多线程应用详解(第三卷:图解多线程中join,守护线程应用)
- python3多线程应用详解(第一卷:线程的本质概念)
之前我用过多线程的方式执行了爬虫程序,爬取了糗事百科的数据可以看到速率非常之快,就像正常一个人他要完一个汉堡,再吃喝一瓶水才能走,结果他边吃汉堡边喝水,速率一下加快了一样.首先我们看看什么是线程: 图 ...
- .NET多线程同步方法详解
.NET多线程同步方法详解(一):自由锁(InterLocked) .NET多线程同步方法详解(二):互斥锁(lock) NET多线程同步方法详解(三):读写锁(ReadWriteLock) .NET ...
- Mac OS X10.9安装的Python2.7升级Python3.4步骤详解
Mac OS X10.9安装的Python2.7升级Python3.4步骤详解 Mac OS X10.9默认带了Python2.7,不过现在Python3.4.0出来了,如果想使用最新版本,赶紧升级下 ...
- Java多线程——多线程方法详解
本系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线程的深入剖 ...
- Swift - 多线程GCD详解
// GCD详解 // 目录: // 1. 创建GCD队列(最常用) // 2. 自定义创建队列 // 3. 使用多线程实现延迟加载 // 4. 使用多线程实现重复(循环) // 5. ...
- python3 常用模块详解
这里是python3的一些常用模块的用法详解,大家可以在这里找到它们. Python3 循环语句 python中模块sys与os的一些常用方法 Python3字符串 详解 Python3之时间模块详述 ...
随机推荐
- C# virtual和abstract的
virtual和abstract都是用来修饰父类的,通过覆盖父类的定义,让子类重新定义. 它们有一个共同点:如果用来修饰方法,前面必须添加public,要不然就会出现编译错误:虚拟方法或抽象方法是不能 ...
- ios openURL的使用(调用系统电话、浏览器、地图、邮件等)
Safari Any URL starting with http:// which does not point to maps.google.com or www.youtube.com is s ...
- 4、C#基础整理(if语句经典习题)
1.用 if 判断输入的是否是空格键的方法:(Console.ReadKey()的用法) ConsoleKeyInfo readkey = Console.ReadKey(); Console.Wri ...
- Selenium - 封装WebDrivers (C#)
Web element仍然使用OpenQA.Selenium.IWebElement, 本类库将Selenium原装支持的各浏览器统一为OnDriver, 并将常用操作封装. using System ...
- iOS-代理
1.协议是一组通讯协议,一般用作两个类之间的通信. 2.协议声明了一组所有类对象都可以实现的接口. 3.协议不是类,用@protocol关键字声明一个协议. 4.与协议有关的两个对象,代理者和委托者. ...
- 扩展KVM镜像的虚拟磁盘大小
当我们需要扩展模板镜像的虚拟磁盘大小时,比如原来的虚拟磁盘大小为20G,现在我们想将其扩展到30G,那么我们可以根据如下步骤来操作. 整个流程可以分为三个阶段: 1.扩展KVM镜像磁盘文件大小到30G ...
- Bash 使用技巧
Bash 是我们经常与之打交道的 Shell 程序,本文针对其使用技巧进行了搜罗.相信在你看过这些内容之后,定会在 Bash 的世界里游刃有余. 从历史中执行命令 有时候,我们需要在 Bash 中重复 ...
- 使用Dnsmasq搭建本地dns服务器上网
导读 搭建一个属于自己的本地DNS服务器很有必要,利用Dnsmasq来搭建一个属于自己的本地DNS服务器,享受更干净无污染.更智能快速和没有广告干扰的DNS解析服务. 一.Dnsmasq安装 安装并启 ...
- linux信号处理及libcurl的坑
前言: 最近有个项目, 需要访问第三方服务. 该服务是通过http的形式访问的, 为了安全和加密, 对方提供了一个加密用的C/C++库, 用于对参数进行处理. 鉴于此, 选用了C/C++语言 ...
- Deep Learning论文笔记之(四)CNN卷积神经网络推导和实现(转)
Deep Learning论文笔记之(四)CNN卷积神经网络推导和实现 zouxy09@qq.com http://blog.csdn.net/zouxy09 自己平时看了一些论文, ...