当前位置: 首页 > news >正文

Python | threading

Python | threading

1. 简介

Python的threading模块是用于创建和管理线程的标准库。线程是在同一进程中执行的多个执行路径,使程序可以同时执行多个任务。

threading模块提供了Thread类,通过创建Thread对象,可以轻松地在Python中启动和管理线程。

2. 多线程

2.1. 继承方式

import threading
import timeclass MyThread(threading.Thread):def run(self):print('start working')time.sleep(1)print('end work')my_thread = MyThread()
my_thread.start()
my_thread.join()

2.2. 回调方式

import threading
import timedef run():print('start working')time.sleep(1)print('end work')my_thread = threading.Thread(target=run)
my_thread.start()
my_thread.join()

3. threading.Lock 锁

import threadingclass Fruits:list: [str] = []lock: threading.Lock = threading.Lock()def add(self, fruit: str):with self.lock:index = self.__get_index(fruit)if index == -1:# 存在更新self.list.append(fruit)def update(self, old: str, new: str):with self.lock:index = self.__get_index(old)if index != -1:# 存在更新self.list[index] = newdef get_index(self, fruit: str) -> int:with self.lock:return self.__get_index(fruit)def __get_index(self, fruit: str) -> int:for index in range(len(self.list)):if self.list[index] == fruit:return indexreturn -1fruits = Fruits()
fruits.add('Banana')
fruits.update('Banana', 'Apple')
print(fruits.get_index('Banana'))
print(fruits.get_index('Apple'))

4. threading.RLock 重入锁

此处RLock并非读写锁,表示重入锁,同一个线程可以多次获取锁。
对比Lock的示例代码,RLock经常使用在一个API既需要内部使用,又需要开放外部访问保证线程安全时特别有用。

import threadingclass Fruits:list: [str] = []lock: threading.RLock = threading.RLock()def add(self, fruit: str):with self.lock:index = self.get_index(fruit)if index == -1:# 存在更新self.list.append(fruit)def update(self, old: str, new: str):with self.lock:index = self.get_index(old)if index != -1:# 存在更新self.list[index] = newdef get_index(self, fruit: str) -> int:with self.lock:for index in range(len(self.list)):if self.list[index] == fruit:return indexreturn -1fruits = Fruits()
fruits.add('Banana')
fruits.update('Banana', 'Apple')
print(fruits.get_index('Banana'))
print(fruits.get_index('Apple'))

5. threading.Timer 非周期性定时器

import threading
import datetimedef work():print(f'hello {datetime.datetime.now()}')timer = threading.Timer(2, work)
# 2秒过后调用work
timer.start()
# timer.cancel()

6. threading.Semaphore 信号量

常用方法

semaphore = threading.Semaphore(value=2)  # 总资源数量2
semaphore.acquire()  # 请求资源
semaphore.release(n=1)  # 释放资源

使用示例:中间件

import threading# 令牌桶,网站同时只允许1000人访问
tokenBucket = threading.Semaphore(value=1000)class HTTPRequest:passdef abort(req: HTTPRequest):passdef next_step(req: HTTPRequest):pass# 模拟HTTP中间件
def middleware(req: HTTPRequest):b: bool = Falsetry:# 获取令牌b = tokenBucket.acquire(blocking=False)if not b:# 失败,中止访问abort(req)# 成功,继续下一步next_step(req)finally:if b:# 归还令牌tokenBucket.release()

7. threading.BoundedSemaphore 边界信号量

threading.Semaphore不同的是,资源数量被限制不能超过初始资源数量。

import threadingsemaphore = threading.BoundedSemaphore(value=10)
semaphore.acquire()
semaphore.release()
# Exception: Semaphore released too many times
semaphore.release()

8. threading.Barrier 栅栏

threading.Barrier 是 Python 中 threading 模块中的同步原语,它用于在多个线程中进行同步,确保这些线程在达到指定的屏障点之前都会被阻塞,然后在所有线程都到达屏障点后同时继续执行。

threading.Barrier 适用于需要所有线程到达某个点之后再继续执行的场景,比如等待所有线程完成一定阶段的工作后再进行下一阶段的操作。

threading.Barrier 的常用方法是:

  1. __init__(parties, action=None): 创建一个 Barrier 对象。parties 参数指定需要等待的线程数量,当有 parties 个线程都调用 wait() 方法后,所有线程将同时释放并继续执行。可选的 action 参数可以指定一个回调函数,当所有线程释放后,此回调函数将在释放线程中的一个线程中执行。
  2. wait(timeout=None): 阻塞线程,直到所有参与线程都调用了 wait() 方法并达到屏障点。可选的 timeout 参数用于设置等待的超时时间,如果超过此时间,线程将被解除阻塞。

下面是 threading.Barrier 的一个简单示例:

import threadingdef worker(barrier, name):print(f"{name}: 执行任务前")barrier.wait()print(f"{name}: 执行任务后")# 创建 Barrier 对象,需要等待3个线程
barrier = threading.Barrier(3)# 创建3个工作线程
thread1 = threading.Thread(target=worker, args=(barrier, "线程1"))
thread2 = threading.Thread(target=worker, args=(barrier, "线程2"))
thread3 = threading.Thread(target=worker, args=(barrier, "线程3"))# 启动工作线程
thread1.start()
thread2.start()
thread3.start()# 等待所有线程完成
thread1.join()
thread2.join()
thread3.join()print("所有线程已完成。")

9. threading.Event 事件

threading.Event 是 Python 中 threading 模块中的同步原语,它允许线程等待直到被其他线程设置为真的事件。它通常用于协调多个线程的活动,并促进它们之间的通信。

threading.Event 的主要作用是为线程提供一个简单的机制,使它们能够在特定条件满足之前暂停执行。与 threading.Event 相关的两个主要方法是:

  1. set(): 设置事件为真。正在使用 wait() 方法等待事件的线程将被释放,可以继续执行。

  2. clear(): 重置事件为假。随后调用 wait() 的线程将被阻塞,直到再次使用 set() 方法设置事件。

除了这两个方法之外,还有 wait(timeout=None) 方法。当线程调用 wait() 时,它将被阻塞,直到事件被设置或达到可选的 timeout 参数为止。如果提供了超时,并且事件在指定的时间内没有被设置,线程将继续执行,而不考虑事件状态。

下面是 threading.Event 的一个基本示例:

import random
import threading
import timeevent = threading.Event()
runners = ['runner1', 'runner2', 'runner3']
threads = []def start(name: str):print(f'{name} 准备就绪')event.wait()print(f'{name} 起跑')time.sleep(random.randint(1, 3))print(f'{name} 到达终点')# 准备
for runner in runners:t = threading.Thread(target=start, args=(runner,))t.start()threads.append(t)# 让所有跑步者都进入等待,此处处理并不优雅,但这里主要目的是为了演示event。
time.sleep(1)
# 发令
event.set()for t in threads:t.join()

10. threading.Condition

threading.Condition 是 Python 中 threading 模块中的同步原语,它用于在多个线程之间进行复杂的协调和通信。它提供了一个通用的条件变量,允许线程等待某个条件为真,或者在满足条件时通知其他等待的线程。

threading.Condition 主要用途是在多线程环境下实现线程间的协作,特别是用于生产者-消费者模式和线程间的消息传递。通过使用 threading.Condition,我们可以让一个线程等待直到满足特定条件,然后另一个线程通知条件已经满足,从而实现线程间的同步。

threading.Condition 的常用方法有:

  1. __init__(lock=None): 创建一个 Condition 对象。可选的 lock 参数指定一个锁对象,用于在内部同步条件的访问。如果不提供锁对象,Condition 会自动创建一个默认的锁对象。
  2. acquire(): 获取底层关联的锁,用于保护共享资源或条件。
  3. release(): 释放底层关联的锁。
  4. wait(timeout=None): 等待条件为真。调用此方法将释放关联的锁并阻塞线程,直到另一个线程调用 notify()notify_all() 方法通知条件为真或超时。
  5. notify(n=1): 唤醒等待此条件的一个线程。默认情况下,唤醒一个等待的线程,如果指定 n 参数,将唤醒 n 个等待的线程。
  6. notify_all(): 唤醒所有等待此条件的线程。

下面是一个使用 threading.Condition 的简单示例:

import threadingcar_condition = threading.Condition()
toll_collector_semaphore = threading.Semaphore(value=0)def waiting_for_release(name: str):print(f'{name} 到达,等待放行')# 记录当前有等待放行toll_collector_semaphore.release()with car_condition:car_condition.wait()print(f'{name} 放行')def toll_collector():while True:toll_collector_semaphore.acquire()with car_condition:# 放行一辆car_condition.notify()cars = ['A', 'B', 'C', 'D']# 启动收费员
threading.Thread(target=toll_collector).start()for car in cars:threading.Thread(target=waiting_for_release, args=(car,)).start()

11. 参考

  • python 实现线程之间的通信
  • Python 多线程编程-07-threading 模块 - Barrier

相关文章:

Python | threading

Python | threading 1. 简介 Python的threading模块是用于创建和管理线程的标准库。线程是在同一进程中执行的多个执行路径,使程序可以同时执行多个任务。 threading模块提供了Thread类,通过创建Thread对象,可以轻松地在Python中启动和管理…...

Unity数字可视化学校_昼夜(二)

1、时间设置: 2、新建夜晚 3、新建侧置球(BOX),测试灯光强度 降低亮度 色调:冷色调 4、自发光 新建shader 灯光控制 道路线: 建筑: 夜晚加灯光: 玻璃: 加大灯光数量: 边缘…...

嘉楠勘智k230开发板上手记录(二)

上次成功在k230上烧录sdk,这次准备实现hello world和ssh scp远程k230 一、PC连接k230 1. 初步准备 首先下载串口工具PuTTY,这个我个人感觉比较方便。 准备两根USB type-C数据线,一根连电源,一根连串口调试。还有Type C公头转网…...

flex 弹性布局

Flex 布局的使用 任何一个容器都可以指定为 Flex 布局。 .box{ display: flex; //flex作为display的一个属性使用 } 行内元素也可以使用 Flex 布局。 .box{ display: inline-flex; } 注意:设为 Flex 布局以后,子元素的float、clear和vertical-align…...

【C# 基础精讲】为什么选择C# ?

C#(C Sharp)是由微软开发的一种通用、面向对象的编程语言。它最初于2000年发布,自那时以来逐渐成为开发者的首选之一。C#的设计目标是提供一种简单、现代、可靠且安全的编程语言,使开发者能够轻松构建各种类型的应用程序。 为什么…...

HCIP BGP选路规则总结

选路前提条件 多条BGP路由目标相同,且均可优(下一跳可达、同步关闭),具有相同的优先级(管理距离)。 1、优选Preference_Value值最高的路由(私有属性,仅本地有效)。 不传递 权限最高属性 可…...

UE4 Cesium for unreal 离线加载应用全流程

参考配置:Win10、请保证是在局域网环境下配置 配置IP 右键选择:打开“网络和Internet” 设置 选择更改适配器选项 请保证以太网是处于启用状态并连接线缆,点击右键选择属性 双击选择Internet协议版本4(TCP/IPv4) 将IP地…...

翻转卡片游戏【力扣822】

解题思路 如果卡片上正面和背面的数字相同,都为x,那么x一定不符合要求,将这些数都记录到哈希表hash中。剩下的卡片正反面数字不相同,那么不在hash中的数字中的最小数min一定是答案。因为若min跟现在front数组中的某些数相同&…...

嵌入式开发学习(STC51-5-数码管)

内容 静态数码管:最左端显示0 动态数码管:从左到右,显示0-9 数码管简介 数码管是一种半导体发光器件,其基本单元是发光二极管; 类别: 数码管按段数可分为七段数码管和八段数码管,八段数码管…...

JavaScript |(四)正则表达式 | 尚硅谷JavaScript基础实战

学习来源:尚硅谷JavaScript基础&实战丨JS入门到精通全套完整版 文章目录 📚正则表达式📚正则表达式字面量方式📚字符串&正则表达式🐇split()🐇search()🐇match()🐇replace()…...

docker-compose实现mysql主从复制

利用docker-compose实现mysql主从复制 1.首先创建挂载的目录以及配置信息 1.1 主 mkdir -p /opt/mysql/master/data mkdir -p /opt/mysql/master/config # 编写配置文件 vim /opt/mysql/master/config/my.cnfmy.cnf配置信息 [mysqld] usermysql default-storage-engineINNO…...

hbase基础

hbase安装 tar -zxvf hbase-2.4.11-bin.tar.gz -C . ln -s f hbase-2.4.11-bin hbasemv /export/server/hbase/lib/client-facing-thirdparty/slf4j-reload4j-1.7.33.jar /export/server/hbase/lib/client-facing-thirdparty/slf4j-reload4j-1.7.33.jar.bakvim conf/regionser…...

【GitOps系列】如何实施自动化渐进式交付?

文章目录 前言自动渐进式交付概述自动渐进式交付准备创建生产环境创建 AnalysisTemplate访问生产环境安装Prometheus配置 Ingress-Nginx 和 ServiceMonitor验证 Ingress-Nginx 指标 自动渐进式交付实战自动渐进式交付成功自动渐进式交付失败 结语 前言 在实施金丝雀发布的过程中…...

【网络】网络层(IP协议)

目录 一、基本概念 二、协议头格式 三、网段划分 四、特殊的IP地址 五、IP地址的数量限制 六、私有IP地址和公网IP地址 七、路由 一、基本概念 IP协议:提供一种能力, 将数据从A主机送到B主机,(TCP协议:确保IP协议…...

Unity数字可视化学校_昼夜(一)

maya2022:链接:https://pan.baidu.com/s/1cvB438UKsv_tU37NsOaNow 3dmax软件合集:百度网盘 请输入提取码 1180 1、 2、unity3d 导入插件 : (1)UniStorm - Volumetric Clouds Sky 5.3.0.unitypackage (天气&…...

QWidget样式

1、设置边框样式: QWidget {font-family:Microsoft YaHei UI;background:#ffffff;/*border:3px solid rgba(207, 209, 208, 170);设置整体边框*/border-bottom: 3px solid rgba(207, 209, 208, 170);/*设置底部边框*/border-top: 3px solid rgba(207, 209, 208, 1…...

TypeScript基础学习

目录 一、安装 1、下载国内镜像 2、安装 3、查看安装情况 4、使用例子 二、变量声明 1、规则 2、声明的四种方式 3、注意 4、类型断言 5、类型推断 6、变量作用域 三、基础类型(共11种) 1、Any 类型 2、Null 和 Undefined 3、never 类型…...

AOF日志:宕机了,Redis如何避免数据丢失

当服务器宕机后,数据全部丢失:我们很容易想到的一个解决方案是从后端数据库恢复这些数据,但这种方式存在两个问题:一是,需要频繁访问数据库,会给数据库带来巨大的压力;二是,这些数据…...

【编程】典型题目:寻找数组第K大数(四种方法对比)

【编程】典型题目:寻找数组第K大数(四种方法对比) 文章目录 【编程】典型题目:寻找数组第K大数(四种方法对比)1. 题目2. 题解2.1 方法一:全局排序(粗暴)2.2 方法二&#…...

Vue3 对比 Vue2 的变化

Vue3 对比 Vue2 的变化 1.源码组织方式变化:使用 TS 重写 2.支持 compositionAPI,基于函数的 api,更灵活组织组件逻辑(Vue2 使用 options api) 3.响应式系统提升:Vue3 的响应式数据原理改成了 Proxy,可以监听动态新增删…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

2025-05-08-deepseek本地化部署

title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek&#xff1a;小白也能轻松搞定&#xff01; 如何给本地部署的 DeepSeek 投喂数据&#xff0c;让他更懂你 [实验目的]&#xff1a;理解系统架构与原…...