2. python協程/異步編程詳解

目錄

1. 簡單的異步程序

2.?協程函數和協程對象

3. 事件循環

4. 任務對象Task及Future對象

? ? ? ? 4.1 Task與Future的關系

? ? ? ? 4.2 Future對象

? ? ? ? 4.3 全局對象和循環事件對象

5. await關鍵字

6. 異步上下文管理

7.異步迭代器

8.?asyncio的常用函數

? ? ? ? 8.1 asyncio.run

????????8.2 asyncio.get_event_loop

? ? ? ? 8.3 asyncio.wait

? ? ? ? 8.4?asynco.gather

? ? ? ? 8.5?asyncio.wait_for

? ? ? ? 8.6?asyncio.create_task和loop.create_task

? ? ? ? 8.7?eventloop.call_later

? ? ? ? 8.8?eventloop.stop與eventloop.close

? ? ? ? 8.9 event.wait和event.set


????????協程(coroutine):類似一種輕量級的多線程程序,是在一個線程里面,實現多任務并行執行的編程方式。相比多線程,它在切換任務時,CPU開銷更低,速度更快。

? ? ? ? 協程實現多任務并行執行實際是通過各任務異步執行來實現的。

????????asyncio?是python異步代碼庫,是幾乎所有python異步實現的基礎,因此,使用python的協程功能,得先掌握asyncio庫的使用。

1. 簡單的異步程序

import asyncio
async def fun1():print('a')await asyncio.sleep(.5)print('b')async def fun2():print('c')await asyncio.sleep(.5)print('d')asyncio.run(asyncio.wait([fun1(),fun2()]))

? ? ? ? 運行結果:?

? ? ? ? 可以看到,雖然fun1和fun2是依次放進事件列表中的,可實際運行結果,并不是abcd,而是cadb,先執行fun2后執行fun1,這里與列表在函數取參時LIFO(后入先出)有關。

? ? ? ? 在執行過程中,fun2先打印字符c后,遇到sleep,并不是原地阻塞0.5秒,而是跳出來,執行fun1,打印a,在fun1中又遇到sleep,這里又跳出來執行fun2,待fun2的掛起時間到了后,執行fun2后續代碼,打印出字符d,fun2結束后又去fun1執行,打印出字符b。

????????這就是異步執行,它并不是順序執行,而是可以暫停當前執行的流程,轉到另一個程序中去執行,之后又回到暫停位置繼續執行。

2.?協程函數和協程對象

????????由async聲明定義的函數,即是協程函數,它直接返回的就是協程對象。

? ? ? ? 協程函數要被執行,須將協程對象交給事件循環來處理,或者通過await關鍵字執行,不能直接執行協程函數。

????????注意,協程函數直接返回協程對象,指函數名()返回,并不是執行結果return返回:

import asyncio
async def fun():await asyncio.sleep(.5)print("This is a coroutine function")return "Hello world"async def main():t = fun()r = await tprint(f"Result:{r}")asyncio.run(main())##運行結果:
This is a coroutine function
Result:Hello world

? ? ? ? 示例中函數名fun()返回的是一個協程對象,它被賦值給t,通過await執行后,fun最后的返回結果放在r中,fun的return返回Hello world,因此最后打印出的r就是Hello world?

3. 事件循環

? ? ? ? 事件循環是asyncio運行的核心,是由循環調度器_event_loop_policy調度加入到Task隊列中的Task對象進行執行。

????????在上面調用asyncio.run函數的時候,該函數實際是創建一個循環調度器,并將將可Task對象放進循環中,然后等待對象執行完成,再退出。它相當于:

eventloop = asyncio.new_event_loop()
asyncio.set_event_loop(eventloop)
eventloop.run_until_complete(obj)

? ? ? ? asyncio.new_event_loop創建一個新的循環調度器,set_event_loop啟用該調度器,run_until_complete將對象obj放入調度器的Tasks隊列中,等待執行完成。

????????事件循環的本質是將所有待執行的協程對象包裝成任務對象(Task對象),將Task對象放入到事件循環隊列中,調度器執行事件循環,當某個對象遇到阻塞,就掛起轉而執行隊列中的其它對象,當掛起時間到了,又回到該對象掛起位置繼續執行。

? ? ? ? run_until_complete函數最后實際是執行loop.run_forever,run_forever是事件循環具體實現代碼,最核心的代碼是:

while True:

? ? ? ? _run_once()

? ? ? ? if _stopping:

? ? ? ? ? ? ? ? break

? ? ? ? 可見,它是一個while循環,直到_stopping置True退出,因此,實際是可以提前退出事件循環的,EventLoop提供了一個API,eventloop.stop()直接置_stopping為True提前退出事件循環?

4. 任務對象Task及Future對象

? ? ? ? 4.1 Task與Future的關系

????????asyncio.Future類是一個基類,asyncio.Task類繼承自Future。事件循環調度器中執行的對象就是任務對象(Task對象),只有Future對象(或Task對象)才能放入進事件循環隊列tasks中。

? ? ? ? 因此,上面示例中,run_until_complete接收的參數應該是Future對象,當run_until_complete傳入一個協程對象后,會先判斷是否為Future對象,如果是協程,則被wrap成Task對象(Task(coro,eventloop)),再將對象注冊(_register_task)到隊列中。

? ? ? ? 4.2 Future對象

????????它表示一個還未完成的工作結果,它有四個基本狀態:

  • Pending
  • Running
  • Done
  • Cancelled

? ? ? ? 事件循環調度器會跟著它的狀態,以判斷它是否被執行完成。Task對象中,當等待Future.result()時,也即任務結整返回,最后執行Future.set_result(value):

import asyncioasync def fun(fut:asyncio.Future):print("This is a coroutine")fut.set_result('ABCDE')async def main():eventloop = asyncio.get_event_loop()fut = eventloop.create_future()eventloop.create_task(fun(fut))r = await futprint(f'Result:{r}')asyncio.run(main())##運行結果:
This is a coroutine
Result:ABCDE

? ? ? ? 分析:asyncio.get_event_loop返回當前執行的EventLoop對象,它由asyncio.run創建。eventloop.create_future()創建一個Future對象,它什么也不做,它被當作參數傳入到協程中;evenloop.create_task()將協程wrap成Task對象,加入到事件循環調度器的任務隊列Tasks中,await fut等待fut有結果,并將結果保存在r中。

????????當協程執行完后,調用fut.set_result就會在Future對象中產生一個值(結果),這時協程返回,await fut就因為fut有結果了結束,將結果返回給r,即ABCD。

? ? ? ? 4.3 全局對象和循環事件對象
t1 = asyncio.create_task(coro)
t2 = eventloop.create_task(coro)
fut1 = asyncio.create_future()
fut2 = eventloop.create_future()

? ? ? ? ayncio和eventloop都能創建Task對象,前者是個全局Task對象,不依賴特定的事件循環,而后者則依賴當前的eventloop事件循環

5. await關鍵字

? ? ? ? await 后面跟可等待對象(awaitable,包括協程對象,任務對象,Future對象),這些對象最終都會被wrap成Task對象執行。await主要作用是暫停當前協程,等待對象執行完成,返回執行結果(函數最后的return),才回到當前協程。

import asyncioasync def fun1():print("This fun1")await asyncio.sleep(.5)print("Fun1 over")return "A fun return."
async def fun2():print("This fun2")await asyncio.sleep(.5)print("Fun2 over")
async def fun3():print("This fun3")await asyncio.sleep(.5)print("Fun3 over")async def main():eventloop = asyncio.get_event_loop()a = eventloop.create_task(fun1())b = asyncio.create_task(fun2())print(f'{await a}')await fun3()await basyncio.run(main())##運行結果:
This fun1
This fun2
Fun1 over
Fun2 over
A fun return.
This fun3
Fun3 over

? ? ? ? 示例分析:eventloop.create_task返回的是協程wrap后的Task對象,分別賦值給變量a和b,await可以作用Task對象,因此,await a得以執行,它等待a執行,直到a返回結果(字符串A fun return,通過print打印出來)。

? ? ? ? 從運行結果看,實際上await a返回時,fun2已經結束了,也就是b對象已經執行結束了,所以,await fun3執行結果并不會出現在a,b對象執行的過程中,后面的await b也不會出現執行結果,因為前面已經執行完了。

? ? ? ? 一個特別的函數:

? ? ? ? await asyncio.sleep(n)

? ? ? ? 它表示暫停當前任務的事件循環控制權,轉而執行其它異步任務,時間到了后,再回到當前協程繼續執行。

6. 異步上下文管理

? ? ? ? python中上下文管理關鍵字with,它可以自動創建資源,并在結束后自動回收資源。with作用于定義了__enter__和__exit__方法的對象。

????????__enter__():定義了進入with代碼塊執行的動作,返回值默認為None,也可以指定某個返回值,返回的接收者就是as后面的變量;

????????__exit__(exc_type, exc_value, traceback):定義了退出with代碼塊執行的動作? ? ??

class Person:def __init__(self):self.name:str = "YSZ"self.score:float = 93.7def __enter__(self):print("Person enter")return selfdef __exit__(self, exc_type, exc_value, traceback):print("Person exit.")with Person() as p:print(f"name:{p.name}")print(f"score:{p.score}")##運行結果:
Person enter
name:YSZ
score:93.7
Person exit.

? ? ? ? 異步上下文管理器是在with前面增加async關鍵字的管理器,類似的,這里作用的對象是定義了__aenter__和__aexit__兩個異步函數的對象:

import asyncioclass Person:def __init__(self):self.name:str = "YSZ"self.score:float = 93.7async def __aenter__(self):print("Person enter")return selfasync def __aexit__(self, exc_type, exc_value, traceback):print("Person exit.")async def main():async with Person() as p:print(f"name:{p.name}")print(f"score:{p.score}")asyncio.run(main())##運行結果
Person enter
name:YSZ
score:93.7
Person exit.

7.異步迭代器

? ? ? ? 一般情況下,可以用for in迭代遍歷的對象都是定義了__iter__,__next__函數的對象,其中:

????????__iter__返回一個可迭代對象iterator

????????__next__返回操作對象,賦給for后面的變量(如下例的i),for不停的迭代,直到引發一個StopIteration異常:

class Person:def __init__(self):self.index = 0self.names:tuple = ("YSZ","TMS","JYN","MOD","GXT","QES")self.name:str = Nonedef __iter__(self):return selfdef __next__(self):self.name = self.names[self.index]self.index += 1if self.index > 5:raise StopIterationreturn selffor i in Person():print(f"name:{i.name} index:{i.index}")##運行結果:
name:YSZ index:1
name:TMS index:2
name:JYN index:3
name:MOD index:4
name:GXT index:5

? ? ? ? 類似的,異步迭代器的對象是定義了__aiter__和__anext__函數的對象,其中:

????????__aiter__函數不能是異步的,它返回一個異步可迭代對象asynchronous iterator,賦給in后面的變量

????????__anext__返回對象必須是可等待(awaitable)對象,因此它必須是一個協程函數。async for不停的迭代,直到引發一個StopAsyncIteration異常停止:?

class Person:def __init__(self):self.index = 0self.names:tuple = ("YSZ","TMS","JYN","MOD","GXT","QES")self.name:str = Nonedef __aiter__(self):return selfasync def __anext__(self):self.name = self.names[self.index]self.index += 1if self.index > 5:raise StopAsyncIterationawait asyncio.sleep(.2)return self.nameasync def main():person = Person()async for i in person:print(f"name:{i}")asyncio.run(main())##運行結果:
name:YSZ
name:TMS
name:JYN
name:MOD
name:GXT

? ? ? ? 注意:async for只能在協程函數中使用

8.?asyncio的常用函數

? ? ? ? 8.1 asyncio.run

? ? ? ? 在第3點已經說明了,它實際是創建了一個新的事件循環調度器,并啟動這個調度器,然后等待傳給它的對象執行完成,它的參數接收可等待對象(協程對象,Task對象,Future對象)

????????8.2 asyncio.get_event_loop

? ? ? ? 返回:事件循環調度器

????????它會獲取當前正在運行的事件循環調度器,相當于asyncio.get_running_loop();

????????如果當前沒有正在運行的事件循環,則創建一個新的事件循環,相當于loop = asyncio.new_event_loop,同時運行這個事件循環:asyncio.set_event_loop(loop),并將這個事件循環調度器返回。

? ? ? ? 8.3 asyncio.wait

? ? ? ? 參數:一組可等待對象列表(list)

????????返回:Future對象

????????作用:等待一組可等待對象完成,最后返回任務結束的結果

? ? ? ? 例如:asyncio.run(asyncio.wait(fun1(),fun2(),fun3()),其中fun1()~fun3()是協程對象

? ? ? ? 8.4?asynco.gather

? ? ? ? 參數:一組可等待對象列表(list)

? ? ? ? 返回:函數名直接返回是Future對象,被await后,返回的是所有對象的執行結果的列表(list)

? ? ? ? 作用:將所有對象幾乎同時全部啟動,實現所有對象高并發運行,通常需要asyncio.Semphore控制并發量,以免資源被占用完:

import asyncioasync def fun(sem,n):async with sem: #每個任務執行前必須獲取信號量print(f"Fun {n} start")await asyncio.sleep(2.0)print(f"Fun {n} over")return nasync def main():sem = asyncio.Semaphore(3)tasks = [fun(sem,n) for n in range(20)]r = await asyncio.gather(*tasks)print(f"Result:{r}")asyncio.run(main())##運行結果:
Fun 0 start
Fun 1 start
Fun 2 start
Fun 0 over
Fun 1 over
Fun 2 over
Fun 3 start
...
Fun 18 start
Fun 19 start
Fun 18 over
Fun 19 over
Result:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

? ? ? ? 示例中gather了20個任務,但是由于限制最高并發量為3,所以,總是三個任務完成后,再進行后面三個,最后的運行結果存放在r中,它是每個任務返回的值組成的列表(list)。

? ? ? ? 特別注意,每個任務在開始執行前都必須要獲取信號,因為實際事件循環是每個任務都去訪問的,但是,規定哪些任務可以執行,就需要這個信號了。

? ? ? ? 8.5?asyncio.wait_for

? ? ? ? 參數:可等待對象,超時的時間timeout

? ? ? ? 返回:可等待對象執行結束后的返回(return)

? ? ? ? 作用:通常和關鍵字await連用,表示對象必須在設定時間內執行完畢,否則拋出一個超時異常asyncio.TimeoutError

import asyncioasync def fun():print("Step1")await asyncio.sleep(.5)print("Step2")await asyncio.sleep(.5)return "Fun back"async def main():try:r = await asyncio.wait_for(fun(),timeout=0.8)print(f"Result:{r}")except asyncio.TimeoutError:print("Object execute timeout.")asyncio.run(main())##運行結果:
Step1
Step2
Object execute timeout.

? ? ? ? 示例中規定了0.8秒內要完成fun()對象,但是里面花了1.0秒,固而拋出超時異常

? ? ? ? 8.6?asyncio.create_task和loop.create_task

? ? ? ? 參數:協程對象

? ? ? ? 返回:Task對象

? ? ? ? 作用:創建一個Task對象,第4.3已經說明了它們的區別,其中loop.create_task同時將創建的對象注冊到任務隊列中了,事件循環會執行它,而asyncio.create_task則是創建一個全局對象,并沒有加到某個事件循環的隊列中,需要await執行

? ? ? ? 8.7?eventloop.call_later

? ? ? ? 參數:時間,回調函數,函數的參數

? ? ? ? 返回:TimerHandle

? ? ? ? 作用:布置一個任務,過了“時間”之后被執行

import asynciodef fun(name:str):print(f"name:{name}  Hello world")async def main():eventloop = asyncio.get_event_loop()eventloop.call_later(1,fun,'YSZ')await asyncio.sleep(3)print("Over!")asyncio.run(main())##運行結果:
name:YSZ  Hello world
Over!

? ? ? ? 示例中布置了一個任務,注意,并非是協程,而是普通函數,并要求在1秒后執行,需要await asyncio.sleep(3)等待,否則循環事件結束了,這個回調還沒執行。?

? ? ? ? 8.8?eventloop.stop與eventloop.close

? ? ? ? 作用:stop停止事件循環,close關閉事件循環。

? ? ? ? 在關閉事件循環之前,需要先檢查事件循環是否正在運行eventloop.is_running(),否則關不了,會觸發一個RuntimeError異常。在正在運行的事件循環中,需要先stop,再close。

? ? ? ? 8.9 event.wait和event.set

? ? ? ? 這兩個函數都是asyncio.Event成員函數,因此調用時,需要:

? ? ? ? event = asyncio.Event()

? ? ? ? event.wait()

? ? ? ? event.set()

? ? ? ? 作用:在有些時候,需要各協程間進行同步,比如有的協程初始化某些外設時間長,有的短,協程初始化外設完成時間可能不一致,而協程接下來的流程又可能用到別的協程外設資源,這時,就需要同步。

? ? ? ? 在需要同步的地方,執行event.wait()阻塞等待,當所有協程都到event.wait()后,執行一次event.set(),這時所有協程都立即從event.wait()返回,繼續后面的流程,這就實現了同步。

? ? ? ? 當需要再次event.wait()阻塞等待時,調用event.clear(),清除set()的標志,然后調用event.wait()即可再次阻塞。

import asyncioasync def fun1(event):print("來這里等著1")await event.wait()print("繼續執行1")async def fun2(event):print("來這里等著2")await event.wait()print("繼續執行2")async def fun3(event):print("模擬初始化3")await asyncio.sleep(2)print("同步其它協程3")event.set()print("繼續執行3")async def main():event = asyncio.Event()event.clear()await asyncio.gather(fun1(event),fun2(event),fun3(event))asyncio.run(main())##運行結果
來這里等著1
來這里等著2
模擬初始化3
同步其它協程3
繼續執行3
繼續執行1
繼續執行2

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/903498.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/903498.shtml
英文地址,請注明出處:http://en.pswp.cn/news/903498.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

智慧園區IOT項目與AI時代下的機遇 - Java架構師面試實戰

在互聯網大廠的Java求職者面試中,面試官通常會針對實際業務場景提出一系列問題。以下是關于智慧園區IOT項目及AI時代下的機遇的面試模擬對話。 第一輪提問 面試官:馬架構,請簡要介紹下智慧園區IOT項目的整體架構設計。 馬架構:…

論文導讀 - 基于特征融合的電子鼻多任務深度學習模型研究

基于特征融合的電子鼻多任務深度學習模型研究 原論文地址:https://www.sciencedirect.com/science/article/pii/S0925400524009365 引用此論文(GB/T 7714-2015): NI W, WANG T, WU Y, et al. Multi-task deep learning model f…

AI超級智能體項目教程(二)---后端項目初始化(設計knif4j接口文檔的使用)

文章目錄 1.選擇JDK的版本和相關配置2.添加依賴信息2.1指定lombok版本信息2.2引入hutool工具類2.3了解knif4j依賴2.4引入knif4j依賴 3.contrller測試3.1完成yml文件配置3.2修改默認掃描路徑3.3controller具體的內容3.4配置接口和訪問路徑3.5如何訪問3.6調試接口3.6調試接口 1.選…

linux blueZ 第四篇:BLE GATT 編程與自動化——Python 與 C/C++ 實戰

本篇聚焦 BLE(Bluetooth Low Energy)GATT 協議層的編程與自動化實踐,涵蓋 GATT 基礎、DBus API 原理、Python(dbus-next/bleak)示例、C/C++ (BlueZ GATT API)示例,以及自動發現、讀寫特征、訂閱通知、安全配對與腳本化測試。 目錄 BLE GATT 基礎概念 BlueZ DBus GATT 模…

kafka與flume的整合、spark-streaming

kafka與flume的整合 前期配置完畢,開啟集群 需求1: 利用flume監控某目錄中新生成的文件,將監控到的變更數據發送給kafka,kafka將收到的數據打印到控制臺(三個node01中運行) 1.在kafka中建立topic kafka…

redis高級進階

1.redis主從復制 redis主從復制1 2.redis哨兵模式 嗶哩嗶哩視頻 redis哨兵模式1 redis哨兵模式2 redis哨兵模式3 3.redis分片集群 redis分片集群1 redis分片集群2 redis分片集群3

uniapp: 低功耗藍牙(BLE)的使用

在微信小程序中實現藍牙對接藍牙秤的重量功能,主要依賴微信小程序提供的低功耗藍牙(BLE)API。以下是一個清晰的步驟指南,幫助你完成從連接藍牙秤到獲取重量數據的開發流程。需要注意的是,具體實現可能因藍牙秤的協議和…

3D架構圖軟件 iCraft Editor 正式發布 @icraft/player-react 前端組件, 輕松嵌入3D架構圖到您的項目

安裝 pnpm install icraft/player-react --saveimport { ICraftPlayer } from "icraft/player-react";export default function MyScene() {return <ICraftPlayer srcyour-scene.iplayer />; }icraft/player-react 為開發者提供了一站式的3D數字孿生可視化解決…

云數據中心整體規劃方案PPT(113頁)

1. 引言 概述&#xff1a;云數據中心整體規劃方案旨在構建彈性、高效的云計算基礎設施&#xff0c;通過軟件定義數據中心&#xff08;SDDC&#xff09;實現資源虛擬化與管理自動化。 2. 技術趨勢與背景 技術革新&#xff1a;隨著云計算、虛擬化及自動化技術的發展&#xff0c…

(六)機器學習---聚類與K-means

到本篇文章&#xff0c;我們先對前幾篇所學習的算法進行一個回顧&#xff1a; 而本篇文章我們將會介紹聚類以及K-means算法。 分類問題回歸問題聚類問題各種復雜問題決策樹√線性回歸√K-means√神經網絡√邏輯回歸√嶺回歸密度聚類深度學習√集成學習√Lasso回歸譜聚類條件隨機…

在html中如何創建vue自定義組件(以自定義文件上傳組件為例,vue2+elementUI)

1、先上代碼&#xff1a;vueUpload.js var dom <div class"upload-file"><el-upload :action"uploadFileUrl" :before-upload"handleBeforeUpload" :file-list"fileList" :limit"limit":on-error"handleUpl…

計算機基礎:二進制基礎14,二進制加法

專欄導航 本節文章分別屬于《Win32 學習筆記》和《MFC 學習筆記》兩個專欄&#xff0c;故劃分為兩個專欄導航。讀者可以自行選擇前往哪個專欄。 &#xff08;一&#xff09;WIn32 專欄導航 上一篇&#xff1a;計算機基礎&#xff1a;二進制基礎13&#xff0c;十六進制與二進…

可視化圖解算法: 判斷是不是二叉搜索樹(驗證二叉搜索樹)

1. 題目 描述 給定一個二叉樹根節點&#xff0c;請你判斷這棵樹是不是二叉搜索樹。 二叉搜索樹滿足每個節點的左子樹上的所有節點的值均嚴格小于當前節點的值&#xff1b;并且右子樹上的所有節點的值均嚴格大于當前節點的值。 數據范圍&#xff1a;節點數量滿足 1≤n≤10^4…

Markdown轉WPS office工具pandoc實踐筆記

隨著DeepSeek、文心一言、訊飛星火等AI工具快速發展&#xff0c;其輸出網頁內容拷貝到WPS Office過程中&#xff0c;文檔編排規整的格式很難快速復制。 注&#xff1a;WPS Office不支持Markdown格式&#xff0c;無法識別式樣。 在這里推薦個免費開源工具Pandoc&#xff0c;實現…

python的turtle庫實現四葉草

實現代碼&#xff1a; import turtle turtle.pencolor(‘green’) turtle.fillcolor(‘green’) turtle.begin_fill() turtle.circle(100,90) turtle.left(90) turtle.circle(100,90) turtle.right(180) turtle.circle(100, 90) turtle.left(90) turtle.circle(100,90) tu…

北重數控滑臺加工廠家:汽車零部件試驗鐵地板-安全性能的測試方法

汽車零部件的安全性能測試是非常重要的&#xff0c;其中鐵地板測試是其中的一種常見測試方法之一。鐵地板測試主要用于評估汽車零部件在發生碰撞或事故時的安全性能&#xff0c;以確保零部件在各種情況下都能提供有效的保護和安全性能。 鐵地板測試通常包括以下步驟和方法&…

Linux0.11系統調用:預備知識

系統調用 預備知識 目標&#xff1a;了解系統調用的流程&#xff0c;在Linux 0.11上添加兩個系統調用&#xff0c;并編寫兩個簡單的應用程序測試它們。 對應章節&#xff1a;同濟大學趙炯博士的《Linux內核0.11完全注釋&#xff08;修正版V3.0&#xff09;》的第5.5節 下面就針…

如何防止 ES 被 Linux OOM Killer 殺掉

當 Linux 系統內存不足時&#xff0c;內核會找出一個進程 kill 掉它釋放內存&#xff0c;旨在保障整個系統不至于崩潰。如果 ES 按照最佳實踐去實施部署&#xff0c;會保留一半的內存&#xff0c;不至于發生此類事情。但事情總有例外&#xff0c;有的朋友可能 ES 和其他的程序部…

swagger2升級至openapi3的利器--swagger2openapi

背景&#xff1a; 因為項目需要升級JDK&#xff0c;涉及到swagger2升級至openapi3的情況。由于swagger 2和openapi 3的語法差距太大&#xff0c;需要對yaml進行升級。無奈單個yaml文件的內容太大&#xff0c;高至4萬多行&#xff0c;手動進行語法的轉換肯定是不可能了&#xff…

在yolo中Ultralytics是什么意思呢?超越分析的智能

在YOLO&#xff08;You Only Look Once&#xff09;目標檢測框架中&#xff0c;Ultralytics 是一家專注于計算機視覺和機器學習技術的公司&#xff0c;同時也是YOLO系列模型&#xff08;如YOLOv5、YOLOv8等&#xff09;的官方開發和維護團隊。以下是關鍵點解析&#xff1a; 1. …