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

python线程、协程

线程

创建线程对象

from threading import Threadt = Thread()
# 功能:创建线程对象
# 参数:target 绑定线程函数
#	args 元组 给线程函数位置传参
#   kwargs 字典 给线程函数键值传参

启动线程

t.start()  # 启动线程

回收线程

t.join([timeout])  # 回收线程

示例

import threading 
from time import sleep,ctimeloops=[4,2]def loop(nloop,nsec):print('start loop',nloop ,' at:',ctime())sleep(nsec)print('loop',nloop ,'done at:',ctime())def main():threads=[]nloops = range(len(loops))for i in nloops:# 注意传参t = threading.Thread(target=loop,args=(i,loops[i]))threads.append(t)for in in nloops:threads[i].start()for i in nloops:threads[i].join()if __name__ == '__main__':main()

自定义线程类

import threading 
from time import sleep,ctimeloops=[4,2]class MyThread(threading.Thread):def __init__(self,func,args,name=''):threading.Thread.__init__(self)self.func = funcself.args = argsself.name = namedef run(self):self.func(*self.args)def loop(nloop,nsec):print('start loop',nloop ,' at:',ctime())sleep(nsec)print('loop',nloop ,'done at:',ctime())def main():threads=[]nloops = range(len(loops))for i in nloops:t = MyThread(loop,(i,loops[i]),loop.__name__)threads.append(t)for in in nloops:threads[i].start()for i in nloops:threads[i].join()if __name__ == '__main__':main()

Event 线程同步

线程之间用于交互的一个对象,这个event是一个内部的标签,线程可以等待这个标签的状态

如果标签(event)没有设置,则线程会一直等待(此时wait是阻塞模式)

import threading 
# 创建线程event对象
e = threading.Event()# 设置e, 使wait结束阻塞
e.wait([timeout]) # 阻塞等待e被set
e.set() # 使e回到未被设置状态
e.clear() # 查看当前e是否被设置
e.is_set() 
import threading
import time
import random# 先定义一个灯的函数,由灯的线程去调用这个函数,绿灯是允许通过,红灯是不允许通过,其中绿灯10s,红灯也是10s,这里就要用到事件
# 如果是绿灯,则设置事件的状态,如果是红灯,则取消事件的状态,初始状态为红灯
def light(event):if event.is_set():#设置初始状态,该初始状态为事件没有状态,则进程一直会阻塞event.clear()count = 0while True:#进入交通灯灯循环的状态if count < 10:print("----red light on----")elif count < 20:print("----green light on----")if not event.is_set():event.set()else:passelse:count = 0if event.is_set():event.clear()count += 1time.sleep(1)# 在定义一个车的函数,由车的线程去调用这个函数
def car(n,event):while True:time.sleep(1)if event.is_set():print("car [%(name)s] is running" %{"name":n})else:print("car [%(name)s] is waiting for red light" % {"name": n})event.wait()if __name__ == '__main__':event = threading.Event()light_thread = threading.Thread(target=light,args=(event,))light_thread.start()for i in range(6):t = threading.Thread(target=car, args=[i,event])t.start()

线程锁 Lock

lock.acquire() 上锁 如果lock已经上锁再调用会阻塞
lock.release() 解锁
with lock: 上锁


with 代码块解锁自动解锁

from threading import Thread, Lock
a = b = 0
lock = Lock()def value():while True:# 上锁lock.acquire()print('a=%d,b=%d' % (a, b)) if a != b else print('a不等于b')# 解锁lock.release()t = Thread(target=value)
t.start()
while True:# with 开始上锁with lock:a += 1b += 1# with 解锁 自动解锁
t.join()
print('程序结束')

协程

协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程。

协程的标准定义:

  • 必须在只有一个单线程里实现并发
  • 修改共享数据不需加锁
  • 用户程序里自己保存多个控制流的上下文栈
  • 一个协程遇到IO操作自动切换到其它协程

协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此,协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。线程是CPU控制的,而协程是程序自身控制的

生成器(yield)

Python中的生成器本身就具有状态保存和恢复的功能,非常适合用来实现协程。生成器协程的最大特点在于使用yield语句来挂起函数并保存函数状态。

def simple_corouctine():print('-> corouctine started')x = yield   # yeild接收my_continue.send发送的信息print('-> corouctine received:',x)# 调用协程
my_corouctine = simple_corouctine()
print(my_corouctine)
# 先启动协程,让协程处于暂停状态
next(my_corouctine) # 程序通过调用方法next()将生成器推进到第一个yield语句处
# 发送消息给协程,回复执行,打印消息
my_corouctine.send('hello world')

async/await

在Python 3.5版本以后,Python提供了原生的支持协程的语法async/await。它提供了更简洁的语法,更好的可读性。

import asyncio async def countdown(n):while n >0 :print(f'T-minux {n}')await asyncio.sleep(1)# yield from asyncio.sleep(1) # 效果同上n -=1loop = asyncio.get_event_loop()
loop.run_until_complete(countdown(5))
import asyncio async def countdown(n,msg):while n >0 :print(f'{msg} - {n}')await asyncio.sleep(1)# yield from asyncio.sleep(1) # 效果同上n -=1
task_list = [asyncio.ensure_future(countdown(5,'A')),asyncio.ensure_future(countdown(2,'B')),asyncio.ensure_future(countdown(3,'C'))
]loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(task_list))

获取返回值

import asyncioasync def firstCorouctine(): # 定义协程await asyncio.sleep(1)return '34434'# coroutine :协同程序 
coroutine = firstCorouctine() # 将协程赋值给coroutine
task = asyncio.ensure_future(coroutine) # 封装为task
loop = asyncio.get_event_loop() # 获取事件循环
loop.run_until_complete(task) # 执行return_value = task.result() # 获取协程返回值
print('协程返回的值为:{}'.format(return_value))

gevent(第三方库)

gevent是一个基于协程的Python网络库,它提供了一种基于yield的编程模型,允许程序员编写异步,非阻塞代码,且易于编写和测试。

安装gevent:pip install gevent

import geventdef func1():print('func1 begin')gevent.sleep(3)print('func1 end')def func2():print('func2 begin')gevent.sleep(2)print('func2 end')def func3(no:int):print('func3 begin')gevent.sleep(2)print('func3 end')g1 = gevent.spawn(func1)
g2 = gevent.spawn(func2)
g3 = gevent.spawn(func3,3) # 传参gevent.joinall([g1, g2, g3])

monkey.path_all

在开头导入monkey.patch_all(),非常重要,会自动将 python 的一些标准模块替换成 gevent 框架,这个补丁其实存在着一些坑:

  • monkey.patch_all(),网上一般叫猴子补丁。如果使用了这个补丁,gevent 直接修改标准库里面大部分的阻塞式系统调用,包括 socket、ssl、threading 和 select 等模块,而变为协作式运行。有些地方使用标准库会由于打了补丁而出现奇怪的问题(比如会影响 multiprocessing 的运行)
  • 和一些第三方库不兼容(比如不能兼容 kazoo)。若要运用到项目中,必须确保其他用到的网络库明确支持Gevent。

在实际情况中协程和进程的组合非常常见,两个结合可以大幅提升性能,但直接使用猴子补丁会导致进程运行出现问题;将 thread 置成 False可以解决该问题,缺点是无法发挥 monkey.patch_all() 的全部性能。

import gevent
from gevent import monkey
monkey.patch_all(thread=False, socket=False, select=False)

pool 限制并发

协程虽然是轻量级线程,但并发数达到一定量级后,会把系统的文件句柄数占光。所以需要通过 Pool 来限制并发数。

import gevent
from gevent.pool import Pool
from gevent import monkey
monkey.patch_all()
import time,datetimedef test(tm):time.sleep(tm)print('时间:{}'.format(datetime.datetime.now()))if __name__ =='__main__':task = []# 限制最大并发pool = Pool(5)# 分配100个任务,最大并发数为5for i in range(100):task.append(pool.spawn(test,5))gevent.joinall(task)

gevent 虽然在编程方面很方便,开头使用 monkey.patch_all(),就能让你的同步代码享受到异步的性能。但坑也是存在的,所以复杂的业务场景不推荐使用 gevent,可以使用python 标准库中的 asyncio。

相关文章:

python线程、协程

线程 创建线程对象 from threading import Threadt Thread() # 功能&#xff1a;创建线程对象 # 参数&#xff1a;target 绑定线程函数 # args 元组 给线程函数位置传参 # kwargs 字典 给线程函数键值传参启动线程 t.start() # 启动线程回收线程 t.join([timeout]) # …...

AttributeError: module ‘OpenSSL.SSL’ has no attribute ‘SSLv3_METHOD

这个错误是由于在OpenSSL.SSL模块中找不到SSLv3_METHOD属性导致的。解决这个问题的方法如下&#xff1a; 首先&#xff0c;确保你已经安装了最新版本的cryptography和pyOpenSSL。你可以使用以下命令卸载并重新安装它们&#xff1a; 卸载cryptography&#xff1a;pip uninstall …...

DTCC 2023丨云原生环境下,需要什么样的 ETL 方案?

​2023年8月16日~18日&#xff0c;第14届中国数据库技术大会&#xff08;DTCC 2023&#xff09;于北京隆重召开&#xff0c;拓数派受邀参与本次大会&#xff0c;PieCloudDB 技术专家邱培峰在大会做了《云原生虚拟数仓 PieCloudDB ETL 方案设计与实现》的主题演讲&#xff0c;详…...

在UE4虚幻引擎中加入导航网格体边界体积后丧尸不能移动和发现玩家

UE4系列文章目录 文章目录 UE4系列文章目录前言一、用到的知识点二、问题原因 前言 最近使用ue4做第一人称视角射击游戏发现问题&#xff0c;加入导航网格体边界体积后丧尸不能移动和发现玩家。下图是出现的问题图片 一、用到的知识点 1.行为树&#xff1a;控制并显示AI的决…...

华为数通方向HCIP-DataCom H12-821题库(单选题:221-240)

第201题 BGP 协议用​​ beer default-route-advertise​​ 命令来给邻居发布缺省路由,那么以下关于本地 BGP 路由表变化的描述,正确的是哪一项? A、在本地 BGP 路由表中生成一条活跃的缺省路由并下发给路由表 B、在本地 BGP 路由表中生成一条不活跃的缺省路由,但不下发给…...

aarch64 arm64 部署 stable diffusion webui 笔记 【1】准备 venv 安装pytorch 验证cuda

aarch64 pytorch(没有aarch64对应版本&#xff0c;自行编译) pytorch-v2.0.1 cuda arm64 aarch64 torch 2.0.1cu118 源码编译笔记【2】验证cuda安装 成功_hkNaruto的博客-CSDN博客 创建venv [rootceph3 stable-diffusion-webui]# /usr/local/Python-3.10.12/bin/python3 -m v…...

从方法到目标了解什么是机器学习?

一、什么是机器学习 1、简述 机器学习是 人工智能(AI) 和计算机科学的一个分支,专注于利用数据和算法来模仿人类的学习方式,逐步提高其准确性。过去几十年来,存储和处理能力方面的技术进步催生了一些基于机器学习的创新产品,例如 Netflix 的推荐引擎和自动驾驶汽车。 机…...

Devos勒索病毒:网络安全的新威胁,勒索病毒解密,数据恢复

随着信息技术的飞速发展&#xff0c;网络安全问题日益凸显。近年来&#xff0c;一种名为Devos的勒索病毒在全球范围内肆虐&#xff0c;给企业和个人带来了极大的损失。本文将详细介绍Devos勒索病毒的特点、传播途径以及预防和应对措施&#xff0c;帮助大家更好地认识和防范这一…...

go语言的高级特性

go语言调用C语言 go tool cgo main.go...

华为VRP系统基本操作

1.实验目的 掌握一些常见的路由命令。 2.实验步骤 查看设备版本信息 display version 修改设备的名字 进入系统视图 system-view修改设备名称 sysname Datacom-Router进入接口视图 int g0/0/1进入到接口GigabitEthernet0/0/1的视图 interface GigabitEthernet 0/0/1dis…...

Milvus Cloud扩展变更:为向量数据库注入前沿增强功能

在向量数据库的不断变化中,Milvus Cloud已成为一个改变游戏规则的先锋,革新了我们存储、搜索和分析复杂向量数据的方式。通过最新版本的Milvus Cloud2.3.0,引入了一系列重要的增强和修改,为更强大、更高效的向量数据库解决方案铺平了道路。在本文中,我们将深入探讨Milvus …...

外观模式简介

概念&#xff1a; 外观模式&#xff08;Facade Pattern&#xff09;是一种结构型设计模式&#xff0c;它提供了一个统一的接口&#xff0c;用于访问子系统中的一组接口。外观模式隐藏了子系统的复杂性&#xff0c;并将其封装在一个简单易用的接口中&#xff0c;使得客户端可以…...

web pdf 拖拽签章

web pdf 拖拽签章 主要通过火狐的pdfjs 来实现 1. 下载js 并编译 地址 https://mozilla.github.io/pdf.js/ 按照官网当下下载并编译就得到了js 2.其实也没有什么好讲的&#xff0c;都是用的js中的方法&#xff0c;官网中都有 按照步骤就能生成一个document元素&#xff0c;然…...

SQLAlchemy 库创建数据库引擎和会话工厂附带SQLSERVER驱动版本确认方式

SQLAlchemy 库创建数据库引擎和会话工厂 from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker# 创建数据库引擎 engine create_engine(mssqlpyodbc://user:passhost:port/database?driverODBCDriver11forSQLServer)# 创建会话工厂 Session sess…...

用Python登录账户

1 问题 如何利用python登录账户&#xff1f; 2 方法 账户和密码存放在文件夹中从文件夹中读取并比较密码密文验证三次后&#xff0c;如不成功则锁定用户 通过。。。。。。。。等证明提出的方法是有效的&#xff0c;能够解决开头提出的问题。 代码清单 1 import osimport getpas…...

梳理下我自已对Reactor与及IO多路复用的select\poll\epoll的理解

Reactor是一种设计思想的落地&#xff0c;其中IO多路复用的具体落地&#xff1a;select\poll\epoll。都是基于Reactor的延伸。它的核心是Reactor与资源处理器。Reactor负责监听与事件的分发&#xff0c;事件包括连接事件、读事件、写事件。 具体的流程是系统调用监听请求&…...

4. 广播变量

一、分区规则&#xff08;DataStream Broadcast&#xff09;和广播变量&#xff08;Flink Broadcast&#xff09; 1.1 DataStream Broadcast&#xff08;分区规则&#xff09; ​ 分区规则是把元素广播给所有的分区&#xff0c;数据会被重复处理。 DataStream.broadcast()1.…...

GPT 内部 — I : 了解文本生成

年轻的陀思妥耶夫斯基被介绍给生成AI&#xff0c;通过Midjourney创建 一、说明 我经常与不同领域的同事互动&#xff0c;我喜欢向几乎没有数据科学背景的人传达机器学习概念的挑战。在这里&#xff0c;我试图用简单的术语解释 GPT 是如何连接的&#xff0c;只是这次是书面形式。…...

平板触控笔哪款好用?好用的第三方apple pencil

而对于那些把ipad当做学习工具的人而言&#xff0c;苹果Pencil就成了必备品。但因为苹果Pencil太贵了&#xff0c;不少的学生们买不起。因此&#xff0c;最佳的选择还是平替电容笔&#xff0c;今天在这里整理了一些高性价比的电容笔&#xff01; 一、挑选电容笔的要点&#xf…...

Mac 上更新系统PATH环境变量

目录 为什么要更新系统的PATH环境变量如何更新系统的PATH环境变量1. 确保你知道工具的实际安装位置。2. 将目录&#xff08;实际安装位置&#xff09;添加到PATH&#xff1a;export PATH$PATH:/path/to/your/tools补充&#xff1a;通过以下方法来确定当前正在使用的是Bash还是Z…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...