python多线程实现
用于线程实现的Python模块
Python线程有时称为轻量级进程,因为线程比进程占用的内存少得多。 线程允许一次执行多个任务。 在Python中,以下两个模块在一个程序中实现线程 -
_thread
模块threading
模块
这两个模块之间的主要区别在于_thread模块将线程视为一个函数,而threading模块将每个线程视为一个对象并以面向对象的方式实现它。 此外,_thread模块在低级线程中有效并且比threading模块具有更少的功能。
_thread 模块
在Python的早期版本中,拥有thread模块,但在相当长的一段时间里它已被视为“已弃用”。 鼓励用户改用threading模块。 因此,在Python 3中,thread模块不再可用。 它已被重命名为_thread,用于Python3中的向后不兼容。
为了在_thread模块的帮助下生成新的线程,我们需要调用它的start_new_thread方法。 这种方法的工作可以通过以下语法来理解 -
_thread.start_new_thread ( function, args[, kwargs] )
这里,
args
是一个参数的元组kwargs
是关键字参数的可选字典
如果想在不传递参数的情况下调用函数,那么需要在args中使用一个空的参数元组。
此方法调用立即返回,子线程启动,并调用与传递的列表(如果有的话)args的函数。 线程在函数返回时终止。
示例
以下是使用_thread模块生成新线程的示例。在这里使用start_new_thread()方法
import _thread
import timedef print_time( threadName, delay):count = 0while count < 5:time.sleep(delay)count += 1print ("%s: %s" % ( threadName, time.ctime(time.time()) ))try:_thread.start_new_thread( print_time, ("Thread-1", 2, ) )_thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:print ("Error: unable to start thread")
while 1:pass
在_thread模块的帮助下理解新线程的生成。
Thread-1: Mon Apr 23 10:03:33 2018
Thread-2: Mon Apr 23 10:03:35 2018
Thread-1: Mon Apr 23 10:03:35 2018
Thread-1: Mon Apr 23 10:03:37 2018
Thread-2: Mon Apr 23 10:03:39 2018
Thread-1: Mon Apr 23 10:03:39 2018
Thread-1: Mon Apr 23 10:03:41 2018
Thread-2: Mon Apr 23 10:03:43 2018
Thread-2: Mon Apr 23 10:03:47 2018
Thread-2: Mon Apr 23 10:03:51 2018
threading模块
threading模块以面向对象的方式实现,并将每个线程视为一个对象。 因此,它为线程提供了比_thread模块更强大,更高层次的支持。该模块包含在Python 2.4中。
threading 模块中的其他方法
threading模块包含_thread模块的所有方法,但它也提供了其他方法。 其他方法如下 -
- threading.activeCount() - 此方法返回处于活动状态的线程对象的数量
- threading.currentThread() - 此方法返回调用者线程控制中的线程对象数。
- threading.enumerate() - 此方法返回当前活动的所有线程对象的列表。
为了实现线程,threading模块具有提供以下方法的Thread类 -
- run() - run()方法是线程的入口点。
- start() - start()方法通过调用run方法来启动线程。
- join([time]) - join()等待线程终止。
- isAlive() - isAlive()方法检查线程是否仍在执行。
- getName() - getName()方法返回线程的名称。
- setName() - setName()方法设置线程的名称。
如何使用 threading 模块创建线程?
在本节中,我们将学习如何使用threading模块创建线程。 按照以下步骤使用threading模块创建一个新线程 -
第1步 - 在这一步中,需要定义Thread类的新子类。
第2步 - 然后为了添加额外的参数,需要重写__init __(self [,args])方法。
第3步 - 在这一步中,需要重写run(self [,args])方法来实现线程在启动时应该执行的操作。
现在,在创建新的Thread子类后,可以创建它的一个实例,然后通过调用start()来启动一个新线程,start()又调用run()方法。
示例
下面这个例子演示如何使用threading模块生成一个新的线程
import threading
import time
exitFlag = 0class myThread (threading.Thread):def __init__(self, threadID, name, counter):threading.Thread.__init__(self)self.threadID = threadIDself.name = nameself.counter = counterdef run(self):print ("Starting " + self.name)print_time(self.name, self.counter, 5)print ("Exiting " + self.name)
def print_time(threadName, delay, counter):while counter:if exitFlag:threadName.exit()time.sleep(delay)print ("%s: %s" % (threadName, time.ctime(time.time())))counter -= 1thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("Exiting Main Thread")
Starting Thread-1
Starting Thread-2
执行上面示例代码,得到以下结果 -
Thread-1: Mon Apr 23 10:52:09 2018
Thread-1: Mon Apr 23 10:52:10 2018
Thread-2: Mon Apr 23 10:52:10 2018
Thread-1: Mon Apr 23 10:52:11 2018
Thread-1: Mon Apr 23 10:52:12 2018
Thread-2: Mon Apr 23 10:52:12 2018
Thread-1: Mon Apr 23 10:52:13 2018
Exiting Thread-1
Thread-2: Mon Apr 23 10:52:14 2018
Thread-2: Mon Apr 23 10:52:16 2018
Thread-2: Mon Apr 23 10:52:18 2018
Exiting Thread-2
Exiting Main Thread
带有线程状态的Python程序
有五种线程状态 - 新的,可运行,运行,等待和死亡。 在这五个中,我们将主要关注三个状态 - 运行,等待和死亡。 一个线程获取处于运行状态的资源,等待处于等待状态的资源; 如果执行和获取的资源的最终版本处于死亡状态。
下面的Python程序在start(),sleep()和join()方法的帮助下将分别显示线程是如何进入运行,等待和死亡状态的
第1步 - 导入必要的模块,threading和time
import threading
import time
第2步 - 定义一个函数,它将在创建线程时调用。
def thread_states():print("Thread entered in running state")
第3步 - 使用time模块的sleep()方法让线程等待2秒钟。
time.sleep(2)
第4步 - 现在,创建一个名为T1的线程,它接受上面定义的函数的参数。
T1 = threading.Thread(target=thread_states)
第5步 - 现在,使用start()函数,可以开始启动线程。 它会产生这个信息,这个信息是在定义函数时设定的。
T1.start()
第6步 - 现在,最后可以在完成执行后使用join()方法终止线程。
T1.join()
在Python中启动一个线程
在python中,可以通过不同的方式启动一个新的线程,但其中最简单的一个就是将其定义为一个单一的函数。 在定义函数之后,可以将它作为新线程的目标。线程对象等等。 执行下面的Python代码来理解函数的工作原理 -
import threading
import time
import random
def Thread_execution(i):print("Execution of Thread {} started\n".format(i))sleepTime = random.randint(1,4)time.sleep(sleepTime)print("Execution of Thread {} finished".format(i))
for i in range(4):thread = threading.Thread(target=Thread_execution, args=(i,))thread.start()print("Active Threads:" , threading.enumerate()
执行上面代码,得到以下结果 -
Execution of Thread 0 started
Active Threads:[<_MainThread(MainThread, started 6040)>,<HistorySavingThread(IPythonHistorySavingThread, started 5968)>,<Thread(Thread-3576, started 3932)>]Execution of Thread 1 started
Active Threads:[<_MainThread(MainThread, started 6040)>,<HistorySavingThread(IPythonHistorySavingThread, started 5968)>,<Thread(Thread-3576, started 3932)>,<Thread(Thread-3577, started 3080)>]Execution of Thread 2 started
Active Threads:[<_MainThread(MainThread, started 6040)>,<HistorySavingThread(IPythonHistorySavingThread, started 5968)>,<Thread(Thread-3576, started 3932)>,<Thread(Thread-3577, started 3080)>,<Thread(Thread-3578, started 2268)>]Execution of Thread 3 started
Active Threads:[<_MainThread(MainThread, started 6040)>,<HistorySavingThread(IPythonHistorySavingThread, started 5968)>,<Thread(Thread-3576, started 3932)>,<Thread(Thread-3577, started 3080)>,<Thread(Thread-3578, started 2268)>,<Thread(Thread-3579, started 4520)>]
Execution of Thread 0 finished
Execution of Thread 1 finished
Execution of Thread 2 finished
Execution of Thread 3 finished
在Python中启动一个线程
在python中,可以通过不同的方式启动一个新的线程,但最简单的就是将其定义为一个单一的函数。 在定义函数之后,可以将它作为新线程的目标。线程对象等等。 执行下面的Python代码来理解函数的工作原理 -
import threading
import timedef nondaemonThread():print("starting my thread")time.sleep(8)print("ending my thread")
def daemonThread():while True:print("Hello")time.sleep(2)
if __name__ == '__main__':nondaemonThread = threading.Thread(target = nondaemonThread)daemonThread = threading.Thread(target = daemonThread)daemonThread.setDaemon(True)daemonThread.start()nondaemonThread.start(
在上面的代码中,有两个函数,分别是- nondaemonThread()和daemonThread()。 第一个函数打印其状态并在8秒后休眠,而deamonThread()函数每2秒无限期地打印出Hello。 我们可以通过以下输出来了解nondaemon和daemon线程之间的区别 -
Hellostarting my thread
Hello
Hello
Hello
Hello
ending my thread
Hello
Hello
Hello
Hello
Hello
相关文章:
python多线程实现
用于线程实现的Python模块 Python线程有时称为轻量级进程,因为线程比进程占用的内存少得多。 线程允许一次执行多个任务。 在Python中,以下两个模块在一个程序中实现线程 - _thread模块threading模块 这两个模块之间的主要区别在于_thread模块将线程视…...

macOS使用CodeRunner快速配置fortran环境
个人网站:xzajyjs.cn 由于一些项目的缘故,需要有fortran的需求,但由于是M1 mac的缘故,不能像windows那样直接使用vsivf这种经典配置。搜了一下网上主流的跨平台方案,主要是gfortran,最近用Coderunner(主要…...

【云原生】k8s 离线部署讲解和实战操作
文章目录一、概述二、前期准备1)节点信息2)修改主机名和配置hosts3)配置ssh互信4)时间同步5)关闭防火墙6)关闭 swap7)禁用SELinux8)允许 iptables 检查桥接流量三、开始部署1&#x…...
【Kubernetes】第十一篇 - 滚动发布的介绍与实现
一,前言 上一篇,介绍了灰度发布和流量切分的集中方式,以及如何实现 k8s 的灰度发布; 本篇,介绍滚动发布的实现; 二,滚动发布简介 滚动发布 滚动发布,则是我们一般所说的无宕机发…...
【尊享版】如何系统构建你的思维认知模型?
超友们,早上好,国庆节快乐~ 今天为你带来的分享是《如何系统构建你的思维认知模型?》,主要分为三个部分: 第一部分:【实现爆发式成长的 10 个思维模型】 第二部分:【6 个不可不知的…...
urho3D编码约定
缩进样式类似于Allman(BSD),即在控制语句的下一行使用大括号,在同一级别缩进。在switch-case语句中,case与switch语句处于相同的缩进级别。 缩进使用4个空格而不是制表符。不应保留空行上的缩进。 类和结构名称以大写…...

Overleaf推广奖励:增加合作者的数量、解锁Dropbox同步和项目修改历史
Overleaf推广奖励 Overleaf是一个LaTeX\LaTeXLATEX在线编译器,它可以让你与合作者共同在线编辑文档。但是默认的免费账号仅能邀请一个合作者。那么如何增加合作者的数量呢? Overleaf推出了一个奖励计划,你邀请其他人注册Overleaf…...

ChatGPT的互补工具Perplexity的详细使用方法(持续更新)
大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,科大讯飞比赛第三名,CCF比赛第四名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…...

【Linux驱动开发100问】如何编译Linux内核?
🥇今日学习目标:如何编译Linux内核? 🤵♂️ 创作者:JamesBin ⏰预计时间:10分钟 🎉个人主页:嵌入式悦翔园个人主页 🍁专栏介绍:Linux驱动开发100问 如何编译…...

15、条件概率、全概率公式、贝叶斯公式、马尔科夫链
条件概率定义:设A、B是两个事件,且,P(A) > 0 则称 为事件A发生的条件下事件B的条件概率对这个式子进行变形,即可得到概率的乘法公式:P(A) > 0 时,则P(B) > 0 时,则乍一看,…...

Eureka服务注册与发现
注册中心是分布式开发的核心组件之一,而Eureka是spring cloud推荐的注册中心实现。简单分析一下Eureka的原理。Eureka基础概念与流程1、服务注册在微服务架构中,一个服务提供者本质上也是一个Eureka客户端。启动时,会调用Eureka所提供的服务注…...
20230226 引用类型和指针类型的区别 - chatGPT
绝了,把chatGPT当百度之后真爽! 引用类型和指针类型都是C语言中的重要概念,它们都提供了访问和操作内存的方法,但它们之间有几个关键的区别。 1. 定义和初始化方式不同 指针类型的变量定义和初始化的方式是通过使用*符号来声明…...

《操作系统》——第二章 进程与线程
目录 2.1.1进程的概念、组成、特征 2.1.2进程的状态与转换、进程的组织 2.1.3进程控制 2.1.4进程通信 2.1.5线程的概念 2.1.6线程的实现方式和多线程模型 2.2.1调度的概念、层次 2.2.2进程调度的时机、切换与过程、方式 2.2.4调度算法的评价指标 2.2.5调度算法(1) 2…...

网络原理之初识
目录 一. 网络互连 1. 局域网 2. 广域网 二. 网络通信基础 1. IP 地址 2. 端口号 3. 网络协议 4. 协议分层 5. TCP/IP 五层网络模型 (简述) 6. 网络数据传输的基本流程 一. 网络互连 随着时代的发展,越来越需要计算机之间互相通信&am…...

CAN总线开发一本全(4) - FlexCAN的驱动程序
CAN总线开发一本全(4) - FlexCAN的驱动程序 苏勇,2023年2月 文章目录CAN总线开发一本全(4) - FlexCAN的驱动程序引言从MindSDK获取FlexCAN驱动程序数据结构配置通信引擎的结构体类型访问MB的结构体类型配置ID过滤器的…...
如何分析linux tcp/ip 丢包问题
引用手把手教你用Dropwatch诊断问题通过dropwatch定位系统内核丢包Finding out if/why a server is dropping packetsgithub source coed: pavel-odintsov/drop_watchHow to drop a packet in Linux in more ways than one试试Linux下的ip命令,ifconfig已经过时了Ho…...
旅游规划(树型dp)
W 市的交通规划出现了重大问题,市政府下定决心在全市各大交通路口安排疏导员来疏导密集的车流。 但由于人员不足,W 市市长决定只在最需要安排人员的路口安排人员。 具体来说,W 市的交通网络十分简单,由 n 个交叉路口和 n−1 条街道…...

【C++】string类的模拟实现
当你将放弃作为一种习惯,你一辈子也不会有出息… 文章目录一、Default member functions1.Constructor2.Copy constructor(代码重构:传统写法和现代写法)3.operator(代码重构:传统写法和现代写法ÿ…...
笔记(一)——STL容器
容器分类:序列式容器:每个元素都有固定位置,取决于插入的时机和地点,和元素无关,如vector、deque、list、stack、queue。关联式容器:元素位置取决于特定的排序准则,和插入顺序无关,如…...
红黑树
红黑树是一个相对的平衡,减少了旋转的消耗 一个节点不是红的就是黑的根节点是黑的一个节点是红的,孩子是黑的(没有连续的红色节点)对于每个节点,从该节点到后代节点的简单路径,都包含相同的黑色࿰…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...

Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...

基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...