多线程概念及其方法讲解

1 认识多线程

1.1 线程的概念

线程是CPU分配资源的基本单位。当一程序开始运行,这个程序就变成了一个进程,而一个进程相当于一个或者多个线程。当没有多线程编程时,一个进程相当于一个主线程;当有多线程编程时,一个进程包含多个线程(含主线程)。使用线程可以实现程序大的开发。

多线程的程序设计的特点就是能够提高程序执行效率和处理速度。

2 线程创建与管理

2.1 创建线程

Python提供了threading模块来进行线程的创建与管理,创建一个线程需要指定该线程执行的任务(函数名)、以及该函数需要的参数,示例代码如下:

import threadingdef demo_one(args):for i in range(5):print("demo1在执行:", i)if __name__ == '__main__':# 创建线程thread_one = threading.Thread(target=demo_one, args=("参数",))# 设置守护线程【可选】thread_one.setDaemon(True)# 启动线程thread_one.start()

1.2 设置守护线程

线程是程序执行的最小单位,Python在进程启动起来后,会自动创建一个主线程,之后使用多线程机制可以在此基础上进行分支,产生新的子线程。子线程启动起来后,主线程默认会等待所有线程执行完成之后再退出。但是我们可以将子线程设置为守护线程,此时主线程任务一旦完成,所有子线程将会和主线程一起结束(就算子线程没有执行完也会退出)。

thread_one.setDaemon(True)
# 方法二
thread_one = threading.Thread(target=demo_one, args=("参数",),daemon=True)

1.3 设置线程阻塞

我们可以用join()方法使主线程陷入阻塞,以等待某个线程执行完毕。因此这也是实现线程同步的一种方式。参数 timeout 可以用来设置主线程陷入阻塞的时间,如果线程不是守护线程,即没有设置daemon为True,那么参数 timeout 是无效的,主线程会一直阻塞,直到子线程执行结束。

# -*- coding:utf-8 -*-
import threadingdef func_one(args):for i in range(5):print("func_one在执行:", i)def func_two(args):for i in range(5):print("func_two在执行:", i)if __name__ == '__main__':# 创建线程thread_one = threading.Thread(target=func_one, args=("参数",), daemon=True)thread_two = threading.Thread(target=func_two, args=("参数",), daemon=True)thread_one.start()thread_two.start()print("程序因线程一陷入阻塞")thread_one.join(timeout=3)print("程序因线程二陷入阻塞")thread_two.join(timeout=3)print("主线程已退出")

1.4 线程间的通信

  1. 线程之间共享同一块内存。子线程虽然可以通过指定target来执行一个函数,但是这个函数的返回值是没有办法直接传回主线程的。我们使用多线程一般是用于并行执行一些其他任务,因此获取子线程的执行结果十分有必要。
  2. 直接使用全局变量虽然可行,但是资源的并发读写会引来线程安全问题。下面给出常用的两种处理方式:

1.4.1 线程锁

其一是可以考虑使用锁来处理,当多个线程对同一份资源进行读写操作时,我们可以通过加锁来确保数据安全。Python中给出了多种锁的实现,例如:同步锁 Lock,递归锁 RLock,条件锁 Condition,事件锁 Event,信号量锁 Semaphore,这里演示 Lock锁的使用方式

from threading import Thread, Lock
from time import sleepbook_num = 100  # 图书馆最开始有100本图书
bookLock = Lock()def books_lease():global book_numwhile True:bookLock.acquire()book_num -= 1print("借走1本,现有图书{}本".format(book_num))bookLock.release()sleep(1)def books_return():global book_numwhile True:bookLock.acquire()book_num += 1print("归还1本,现有图书{}本".format(book_num))bookLock.release()sleep(1)if __name__ == "__main__":thread_lease = Thread(target=books_lease)thread_return = Thread(target=books_return)thread_lease.start()thread_return.start()

1.4.2 queue队列

或者,我们可以采用Python的queue模块来实现线程通信。Python中的queue模块实现了多生产者、多消费者队列,特别适用于在多线程间安全的进行信息交换。该模块提供了4种我们可以利用的队列容器

  • 队列当中的方法
Queue(maxsize=5)  # 创建一个FIFO队列,并制定队列大小,若maxsize被指定为小于等于0,则队列无限大Queue.qsize() # 返回队列的大致大小,注意并不是确切值,所以不能被用来当做后续线程是否会被阻塞的依据Queue.empty() # 判断队列为空是否成立,同样不能作为阻塞依据Queue.full()  # 判断队列为满是否成立,同样不能作为阻塞依据Queue.put(item, block=True, timeout=None) # 投放元素进入队列,block为True表示如果队列满了投放失败,将阻塞该线程,timeout可用来设置线程阻塞的时间长短(秒);
# 注意,如果block为False,如果队列为满,则将直接引发Full异常,timeout将被忽略(在外界用try处理异常即可)
Queue.put_nowait(item) # 相当于put(item, block=False)Queue.get(block=True, timeout=False) # 从队列中取出元素,block为False而队列为空时,会引发Empty异常
Queue.get_nowait() # 相当于get(block=False)Queue.task_done() # 每个线程使用get方法从队列中获取一个元素,该线程通过调用task_done()表示该元素已处理完成。Queue.join() # 阻塞至队列中所有元素都被处理完成,即队列中所有元素都已被接收,且接收线程全已调用task_done()。

生产者消费者实例:

# -*- coding:utf-8 -*-
import threading
from queue import Queue
from random import choicedealList = ["红烧猪蹄", "卤鸡爪", "酸菜鱼", "糖醋里脊", "九转大肠", "阳春面", "烤鸭", "烧鸡", "剁椒鱼头", "酸汤肥牛", "炖羊肉"]queue = Queue(maxsize=5)
# 厨子生产
def func_one(name):for num in range(4):# 随机从列表当中获取一个元素data_veg = choice(dealList)queue.put(data_veg, block=True)print(f"厨师{name}给大家做了一道:{data_veg}")# 客人消费
def func_two(name:str):for num in range(3):veg_data = queue.get()print(f"客人{name}吃掉了:{veg_data}")queue.task_done()if __name__ == '__main__':# 创建生产者线程,总共三个厨子,相当于给每个厨子创建了一个县城for name in ["张三", "李四", "王五"]:thread_one = threading.Thread(target=func_one, args=(name,))thread_one.start()# 创建消费者四个线程for name in ["客人甲", "客人乙", "坤哥", "凡哥"]:thread_two = threading.Thread(target=func_two, args=(name,))thread_two.start()queue.join()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/181503.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

接手了一个外包开发的项目,我感觉我的头快要裂开了~

嗨,大家好,我是飘渺。 最近,我和小伙伴一起接手了一个由外包团队开发的微服务项目,这个项目采用了当前流行的Spring Cloud Alibaba微服务架构,并且是基于一个“大名鼎鼎”的微服务开源脚手架(附带着模块代…

2024年NPDP考试费用明细!报名前必看

随着产品开发和管理在各个行业的发展,产品经理认证(NPDP)逐渐成为了一项重要的职业资质。NPDP认证由国家引进,并由中国国际人才交流基金会负责在国内推广。本文将详细介绍NPDP的报考条件、费用等等,帮助有意参加该考试…

【工具使用】Keil常用的调试操作整理介绍

目录 一、软件调试使用 1.1 基本调试操作 1.2 调试窗口 二、注意事项 一、软件调试使用 1.1 基本调试操作 上文已经说过在线调试和模拟调试的配置过程,但无论是在线还是模拟调试,调试技巧工具的使用都是一样的。 点击红色d,进入调试 可…

C++ 红黑树的封装

一.map/set的封装 在实现了红黑树的部分功能后,我们可以便可以将红黑树作为底层结构来封装map 和 set ,但是问题也随之而来。我们都知道map是k-v的数据模型,而set是k的数据模型,我们难道要去使用两棵红黑树来封装吗?显…

Centos7安装配置nginx

快捷查看指令 ctrlf 进行搜索会直接定位到需要的知识点和命令讲解(如有不正确的地方欢迎各位小伙伴在评论区提意见,小编会及时修改) Centos7安装配置nginx Nginx介绍 Nginx (engine x) 是一个高性能的 HTTP 和 反向代理 服务,也…

Element-plus消息框显示不正常解决方案

Element-plus消息框显示不正常解决方案 不知道问题出现在哪里,反正就是点击按钮并没有在页面上弹出对应的框,而是在某个角落显示,经常遇到,老是忘记怎么写,记录一下解决方案 // import ./assets/main.css import /st…

使用MAT分析内存泄漏(mac)

前言 今天主要简单分享下Eclipse的Memory Analyzer在mac下的使用。 一、Mat(简称)干什么的? 就是分析java内存泄漏的工具。 二、使用步骤 1.下载 mac版的现在也分芯片,别下错了。我这里是M2芯片的,下载的Arch64的。 …

在Mysql中,什么是回表,什么是覆盖索引,索引下推?

一、什么是回表查询? 通俗的讲就是,如果索引的列在 select 所需获得的列中(因为在 mysql 中索引是根据索引列的值进行排序的,所以索引节点中存在该列中的部分值)或者根据一次索引查询就能获得记录就不需要回表&#x…

WPF前端实现人脸扫描动画效果

前言 本章实现的效果主要通过OpacityMask与LinearGradientBrush(径向渐变) 的组合应用来实现。最终实现效果如下: LinearGradientBrush线性渐变画刷 LinearGradientBrush其实很简单,我们只需要关注5个属性,使用这5个属性你就可以完成这个画刷几乎所有的变化。 属性介…

FOC系列(三)----AS5600磁编码器

一、 关于AS5600 1.1 芯片内部框图和引脚功能介绍 具体的内容大家可以查看数据手册:AS5600数据手册,在这里只是对一下重要的地方进行说明。    系统框图如下:    电源设计选项,我在设计时选择的是第二种电源方案&#xff0c…

推荐6款交互设计软件,助你事半功倍!

交互软件可以帮助设计师从“可用性”和“用户体验”的角度优化他们的作品。如果设计师想创建一个令人满意的交互设计作品,一个方便的交互设计软件是必不可少的。当然,交互软件只是我们实现目标的一种手段。根据设计师的个人喜好和方便,选择易…

可以免费使用的Axure在线版来了

Axure作为一种功能强大的原型设计工具,一直受到设计师的青睐。然而,其高昂的价格可能成为一个门槛,限制了一些设计师的选择。但不用担心,现在有一个免费的Axure在线工具即时设计,功能更完整,更划算&#xf…

基于字面的文本相似度计算和匹配搜索

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

Moonsong Labs:融合创业工作室与协议工程专业知识的全新实验室

在这个科技不断变革的世界中,我们很高兴介绍Moonsong Labs — — 一个提供创业工作室和工程服务的实验室。共同塑造当今的创新,同时预测明天的技术风口。在Moonsong Labs,我们的创业工作室和工程专业知识汇聚在一起,推动各种项目&…

基于PaddleOCR银行卡识别实现(三)

前言 基于PaddleOCR银行卡识别实现(一) 基于PaddleOCR银行卡识别实现(二) 前两篇文章讲了检测模型和识别模型的实现,这一篇文章姗姗来迟,将讲解下两个模型的串联应用和PaddleOCR的源码精简,下面…

陪诊系统:基于自然语言处理的患者沟通创新

医疗领域的数字化转型正日益引入创新技术,其中基于自然语言处理(NLP)的陪诊系统成为提升患者沟通的一项关键技术。本文将深入研究这一领域,介绍陪诊系统如何借助NLP实现患者沟通的创新,并提供一个简单的Python代码示例…

windows 服务的安装、启动、状态查询 c++实现

#ifndef __SERVICEMANAGE_H__ #define __SERVICEMANAGE_H__ #include <windows.h> #include <string> class ServerManage { public: ServerManage() {} ~ServerManage() {} /* 根据服务名启动服务 */ inline bool Start_Server(const st…

VUE本地idea启动

安装yarn&#xff08;也可以用npm&#xff09; 问题&#xff1a;yarn : 无法加载文件 C:\Users\xx/yarn.ps1&#xff0c;因为在此系统上禁止运行脚本 解决办法&#xff1a;管理员身份运行【 PowerShell】&#xff0c;然后执行【Set-ExecutionPolicy RemoteSigned】&#xff0c…

CentOS 系统给nodejs 项目安装依赖报错 make: g++: No such file or directory

我在给nodejs 项目安装依赖包的时候&#xff0c;报了如下错误 error /var/www/bsrm-api/node_modules/sleep: Command failed. Exit code: 1 Command: node-gyp rebuild Arguments: Directory: /var/www/bsrm-api/node_modules/sleep Output: gyp info it worked if it ends wi…

onnx快速部署YOLO模型

1、准备和环境 首先需要将yolov5模型训练好的最佳权重文件转化为.onnx格式以备使用。不会的小伙伴可以参考yolov5的官方文档&#xff0c;使用yolov5官方的 export.py 脚本进行转换&#xff0c;或者参考一些博客链接&#xff0c;这里不做详细解析。  基本环境配置&#xff0c;相…