python多任务-线程
多任务的概念
什么叫“多任务”呢?简单地说,就是操作系统可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听MP3,一边在用Word赶作业,这就是多任务,至少同时有3个任务正在运行。还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已。
现在,多核CPU已经非常普及了,但是,即使过去的单核CPU,也可以执行多任务。由于CPU执行代码都是顺序执行的,那么,单核CPU是怎么执行多任务的呢?
答案就是操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像所有任务都在同时执行一样。
真正的并行执行多任务只能在多核CPU上实现,但是,由于任务数量远远多于CPU的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行。
注意:
- 并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)
- 并行:指的是任务数小于等于cpu核数,即任务真的是一起执行的
线程基础
python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便的被使用
单线程执行
import time
def test():
print("test...")
time.sleep(1)
if __name__ == '__main__':
for i in range(5):
test()
执行效果:程序在控制台每隔一秒打印test...
多线程执行
import time
import threading
def test():
print("test...")
time.sleep(1)
if __name__ == '__main__':
for i in range(5):
t = threading.Thread(target=test)
t.start() # 启动线程
执行效果:程序在控制台一下子输出五行test...,等待1秒左右结束
说明:
- 可以明显看出使用了多线程并发的操作,花费时间要短很多
- 当调用
start()时,才会真正的创建线程,并且开始执行
主线程会等待所有子线程结束后才结束
import time
import threading
def playPhone():
print('玩手机...')
time.sleep(1)
def eat():
print("吃东西...")
time.sleep(1)
if __name__ == '__main__':
print("--开始--")
t1 = threading.Thread(target=playPhone)
t1.start()
t2 = threading.Thread(target=eat)
t2.start()
print('--执行结束')
执行效果:主线程阻塞1秒左右后程序结束,说明主线程在等待其他线程执行完毕。
查看线程数量
print('玩手机...')
time.sleep(1)
def eat():
for i in range(10):
print("吃东西...")
time.sleep(1)
if __name__ == '__main__':
print("--开始--")
t1 = threading.Thread(target=playPhone)
t1.start()
t2 = threading.Thread(target=eat)
t2.start()
# 查看正在执行的线程数量
while True:
length = len(threading.enumerate())
print("当前运行的线程数量:%d" % length)
print("这些线程是:%s" % str(threading.enumerate()))
if length == 1:
break
time.sleep(0.5)
print('--执行结束')
在python中,调用threading.enumerate()能获取当前正在运行的所有线程,返回值是一个list,调用length()函数并传入该list对象就获取到当前运行线程的数量。
线程-注意点
线程执行代码的封装
通过上一篇,能够看出,通过使用threading模块能完成多任务的程序开发,为了让每个线程的封装性更完美,所以使用threading模块时,往往会定义一个新的子类class,只要继承threading.Thread就可以了,然后重写run方法。
示例如下:
import time
import threading
class MyThread(threading.Thread):
def run(self):
for i in range(5):
time.sleep(1)
print("我是%s@%d" % (self.name, i))
if __name__ == "__main__":
mt = MyThread()
mt.start()
运行结果如下:
我是Thread-1@0
我是Thread-1@1
我是Thread-1@2
我是Thread-1@3
我是Thread-1@4
python的threading.Thread类有一个run方法,用于定义线程的功能函数,可以在自己的线程类中覆盖该方法。而创建自己的线程实例后,通过Thread类的start方法,可以启动该线程,交给python虚拟机进行调度,当该线程获得执行的机会时,就会调用run方法执行线程。
线程的执行顺序
mport time
import threading
class MyThread(threading.Thread):
def run(self):
for i in range(5):
time.sleep(1)
print("我是%s@%d" % (self.name, i))
if __name__ == "__main__":
for i in range(5):
mt = MyThread()
mt.start()
执行结果(运行的结果可能不一样,但是大体是一致的):
我是Thread-5@0
我是Thread-2@0
我是Thread-3@0
我是Thread-4@0
我是Thread-1@0
我是Thread-3@1
我是Thread-4@1
我是Thread-2@1
我是Thread-5@1
我是Thread-1@1
我是Thread-3@2
我是Thread-4@2
我是Thread-2@2
我是Thread-5@2
我是Thread-1@2
我是Thread-3@3
我是Thread-4@3
我是Thread-2@3
我是Thread-5@3
我是Thread-1@3
我是Thread-3@4
我是Thread-4@4
我是Thread-5@4
我是Thread-2@4
我是Thread-1@4
从代码和执行结果我们可以看出,多线程程序的执行顺序是不确定的。当执行到sleep语句时,线程将被阻塞(Blocked),到sleep结束后,线程进入就绪(Runnable)状态,等待调度。而线程调度将自行选择一个线程执行。上面的代码中只能保证每个线程都运行完整个run函数,但是线程的启动顺序、run函数中每次循环的执行顺序都不能确定。
总结
- 每个线程默认有一个名字,尽管上面的例子中没有指定线程对象的name,但是python会自动为线程指定一个名字。
- 当线程的run()方法结束时该线程完成。
- 无法控制线程调度程序,但可以通过别的方式来影响线程调度的方式。
python多任务-线程的更多相关文章
- Python 多任务(线程) day1
多任务就是可以让一台电脑同时执行多个命令. 以前的单核cpu是怎么做到同时执行多个命令的?(时间片轮转) ——其实以前的单核CPU是让操作系统交替执行命令,每个任务执行0.01秒,这样看起来就像是在同 ...
- Python多任务—线程
并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已) 并行:指的是任务数小于等于cp ...
- Python 多任务(线程) day2 (1)
结论:多线程全局变量是共享的 (03) 因为多线程一般是配合使用,如果不共享,那么就要等到一个线程执行完,再把变量传递给另一个线程,就变成单线程了 但是如果多个线程同时需要修改一个全局变量,就会出现资 ...
- Python(线程进程3)
四 协程 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切 ...
- Python之线程、进程和协程
python之线程.进程和协程 目录: 引言 一.线程 1.1 普通的多线程 1.2 自定义线程类 1.3 线程锁 1.3.1 未使用锁 1.3.2 普通锁Lock和RLock 1.3.3 信号量(S ...
- python/进程线程的总结
python/进程线程的总结 一.进程和线程的描述: 进程:最小的资源管理单位 线程:最小的执行单位 执行一个进程时就默认执行一个线程(主线程) 进程和线程的工作方式: 串行: 假如共有A.B.C任务 ...
- 在python中单线程,多线程,多进程对CPU的利用率实测以及GIL原理分析
首先关于在python中单线程,多线程,多进程对cpu的利用率实测如下: 单线程,多线程,多进程测试代码使用死循环. 1)单线程: 2)多线程: 3)多进程: 查看cpu使用效率: 开始观察分别执行时 ...
- python中线程和进程(一)
目录 进程和线程 Python中的线程 1. Thread类 2. 线程的启动 3. 线程的传参 4. 线程的属性和方法 5. daemon线程和non-daemon线程 6. join方法 7. 定 ...
- 一文了解Python的线程
问题 什么是线程? 如何创建.执行线程? 如何使用线程池ThreadPoolExecutor? 如何避免资源竞争问题? 如何使用Python中线程模块threading提供的常用工具? 目录 1. 什 ...
随机推荐
- 用apache和tomcat搭建集群,实现负载均衡
型的企业应用每天都需要承受巨大的访问量,在着巨大访问量的背后有数台服务器支撑着,如果一台服务器崩溃了,那么其他服务器可以使企业应用继续运行,用户对服务器的运作是透明化的,如何实现这种透明化呢?由如下问 ...
- sql并集union和union all的区别
union : 对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序; union all: 对两个结果集进行并集操作,包括重复行,不进行排序; intersect : 对两个结果集进行交 ...
- 六、activiti工作流-流程定义查询
本节主要讲流程定义查询.查询某个流程设计图片并保存到本地中.查询最新版本的流程定义集合.删除所有key相同的定义 先创建一个java类 package com.java.procdef; import ...
- Scala - 快速学习08 - 函数式编程:高阶函数
函数式编程的崛起 函数式编程中的“值不可变性”避免了对公共的可变状态进行同步访问控制的复杂问题,能够较好满足分布式并行编程的需求,适应大数据时代的到来. 函数是第一等公民 可以作为实参传递给另外一个函 ...
- Python中的高级变量类型
高级变量类型 目标 列表 元组 字典 字符串 公共方法 变量高级 知识点回顾 Python 中数据类型可以分为 数字型 和 非数字型 数字型 整型 (int) 浮点型(float) 布尔型(bool) ...
- c++模板参数——数值类型推断
模板类中,或模板函数中,若限定模板参数为数值类型,可以使用如下方式进行判断. template<typename T> Fmt::Fmt(const char *fmt, T val) { ...
- 运维笔记--docker odoo镜像 运行异常处理
场景描述: 镜像来源,dockerhub odoo官方镜像:https://hub.docker.com/_/odoo odoo镜像运行一段时间后,出现下述异常,可能是触发某个未知bug:该现象在生产 ...
- 扒一扒.net、.net framework、mono和Unity
zhaichao 标签: .net.net frameworkc#monounity 2017-04-23 14:39 425人阅读 评论(0) 收藏 举报 版权声明:本文为博主原创文章,未经博主允许 ...
- SHOW INDEX 你用过吗???
mysql中 show 包含了很多指令,例如show table status, show innodb 等等等, 今天来讲讲mysql中SHOW INDEX FROM tableName 本例中用 ...
- 利用 ELK 搭建 Docker 容器化应用日志中心
利用 ELK 搭建 Docker 容器化应用日志中心 概述 应用一旦容器化以后,需要考虑的就是如何采集位于 Docker 容器中的应用程序的打印日志供运维分析.典型的比如SpringBoot应用的日志 ...