成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

并發實現:掌握不同并發框架的選擇和使用秘訣

開發 前端
在 Spring Boot 2.0 版本之后,也提供了對 Reactor 的全面支持,可以支持你去實現事件驅動模型的后端開發,從而更好地發揮軟件的性能優勢。

不同編程語言中的并發框架種類繁多。例如,Java 語言有 Thread Pool 框架、Akka 框架、Reactor 響應式框架等;C++ 語言有 CAF 框架、Theron 框架等;Go 語言有 goroutine 等。

這些并發框架之間差異很大,若選擇或使用不當,容易導致開發出的軟件性能較差。并且,現在仍有不少程序員對這些并發框架缺乏系統認識,在選擇和使用時較為隨意。

接下來,就讓我們從最為熟悉的 Thread Pool 框架開始學習吧。

Java Thread Pool 框架

Java 的 Thread Pool 框架目前極為流行,原因在于其使用便捷且適用場景眾多。同時,它還是其他并發框架(例如 Akka)內部實現所依賴的技術,所以對這個框架的理解和學習至關重要。那么,為了能夠更好地理解 Java Thread Pool 框架,我們先來查看一下它的框架模型圖:

圖片圖片

從圖的左側開始看,具體實現了接口 Runnable、Callable 的任務,在調用 ExecutorService.submit 接口時,會將任務提交到 ExecutorService 內部的一個任務隊列中。

與此同時,ExecutorService 內部還存在一個預先申請的線程池(Thread Pool)。線程池中的線程會從任務隊列中領取一個任務來執行。

由此我們能夠發現,在 Java 語言中,與直接在代碼中創建線程相比,采用 Thread Pool 這種機制有很多好處。

第一個好處是,在 Thread Pool 中,可以重復利用已創建的線程資源,從而減少線程創建和銷毀造成的額外開銷。第二個好處是,當有新業務請求到達時,可以直接使用已創建的線程來處理業務,所以還可以最大化地減少處理時延。

實際上,對于一個軟件系統而言,線程是非常重要的稀缺資源。而線程池技術也是有效管理線程資源、最大化提升軟件性能的關鍵手段之一。

然而,我見過不少的軟件系統,在使用線程池時根本沒有章法。每個開發人員在自己的業務模塊中隨意創建線程池。而對于整個軟件系統來說,業務代碼中一共創建了多少個線程池、每個線程池的資源規模配置如何,都是很含糊的。從而就導致開發出的軟件性能總是處于不可控的狀態。

所以通常情況下,在使用線程池設計并發系統時,需要對線程池的創建與配置進行全局設計。這里就產生了問題,即應該依據什么規則來劃分線程池組?以及如何配置線程池使用的資源呢?實際上,以我的實踐經驗來看,我認為應該從以下兩個維度來劃分線程池組。

首先,應根據不同的業務邏輯特點進行劃分。例如,可以把以 CPU 計算為主和以 IO 處理為主的業務邏輯劃分到不同的線程池組中。其次,還可以根據不同業務功能的優先級來劃分出不同的線程池組。

當線程池組的劃分確定之后,就可以根據 JVM 中可用的 CPU 核資源數目(可使用 Runtime.getRuntime ().availableProcessors () 獲取 JVM 可用的 CPU 核數),為不同的線程池組分配合理的線程資源額度。

然后,在為線程池組配置可用的線程資源時,需要針對不同線程池上的業務特點,選擇不同的線程資源配置策略。比如,針對 CPU 計算密集型業務,只需讓線程池配置的可用線程數與可分配的 CPU 核數相等即可;而針對 IO 密集型業務,由于業務中的阻塞請求較多,所以可以將配置的線程數提高到可用 CPU 核數的兩倍以上。

當然,我這里只是介紹了大體的配置思路,當你在為線程池組配置可用的線程時,最好是基于真實的業務運行特性分析,并從全局統籌分配之后,再為每個線程池配置合適的線程資源。

好的,現在我們再次回顧前面的線程池框架模型圖。不知你是否注意到,這個框架模型中并未考慮線程之間的通信機制應如何實現。此時你可能會思考:當業務中的線程之間存在信息交互時,該怎么辦呢?這時,你肯定會想到可以基于 Java 并發消息隊列進行通信,還可以使用各種同步互斥鎖。的確,在 Java 語言中,內置的并發消息隊列與互斥鎖等機制幾乎可以滿足線程間的各種同步交互需求,若合理設計并使用,也能很好地發揮軟件性能。然而,在真實的業務開發過程中,并發消息隊列和鎖機制若使用不當,不僅容易導致軟件出現嚴重故障,還容易使系統中的某些線程長時間阻塞,從而不能很好地滿足業務的性能需求。另外,并發消息隊列和鎖在解決同步互斥和數據一致性問題時帶來的內部開銷也會在一定程度上消耗軟件的性能。那么,有沒有不需要直接使用并發消息隊列和鎖就能設計和實現高并發系統的框架呢?答案當然是有,接下來我要為你介紹的 Akka 并發框架,就是為了解決這個問題。

Akka 并發框架

首先我們知道,Akka 是基于 Actor 模型實現的一套并發框架。所以這里,我們同樣是先通過一個 Actor 核心模型圖,來了解下 Akka 并發框架的特點:

圖片圖片

在這個模型圖中,每個 Actor 代表著可以被調度執行的輕量單元。如圖所示,當 Actor A 和 Actor C 向 Actor B 發送消息時,所有消息會被底層框架發送到 Actor B 的 Mailbox 中。然后,底層的 Akka 框架調度代碼會觸發 Actor B,使其接收并執行消息的后續處理。

這樣一來,基于 Actor 模型的這套并發框架,首先保證了消息能夠安全地在各個 Actor 之間傳遞,同時也確保了每個 Actor 實例可以串行處理接收到的所有消息。

因此,在采用基于 Actor 模型的 Akka 框架開發實現軟件時,你無需關注底層的并發交互同步問題,只需聚焦于業務中每個 Actor 實現的業務邏輯,即它需要接收什么消息,又需要向誰發送什么消息。

另外,由于 Actor 模型中的消息機制實現了消息在 Actor 之間傳遞時會被串行處理,所以天然避免了在消息交互中需要解決的數據一致性問題。也就是說,針對系統中并發單元間存在大量信息交互的場景,選用 Akka 并發框架在性能上會有一定優勢。

其實,Actor 模型還有一個更大的優勢,那就是 Actor 非常輕量。它可以支持很大規模的并發,并負載均衡到各個 CPU 核上,從而充分發揮硬件資源,進一步提升軟件的運行性能。那么接下來,為了更好地理解這個原理,我們來看一個任務拆分示意圖。它描述了兩種不同的任務拆分方式,以及將拆分的子任務映射到 CPU 具體核上的執行過程。

圖片圖片

在圖中,左側的方法 1 代表傳統基于線程的粒度并發拆分??梢园l現,在這里想要拆分成大小均勻的并發子任務其實很有挑戰。當拆分出的子任務大小規模差別較大時,將它們映射到底層 CPU 的核上執行,會造成 CPU 核上的負載不均衡。也就是說,傳統的任務拆分方式會出現某些核處于空閑狀態,而另外的核上還有線程在執行的場景。在這種情況下,CPU 多核的性能空間就無法發揮到極致。

而圖中右側的方法 2 代表 Actor 的細粒度任務拆分。它可以把業務功能拆分成大量輕量級的 Actor 子任務。由于每個 Actor 都非常輕量,Akka 的底層調度框架就可以將這些 Actor 子任務均勻地分布到多個 CPU 硬件核上,從而最大化地發揮 CPU 的性能。

所以,在實際的業務開發中要注意,如果在使用 Actor 時,沒有利用好 Actor 輕量級的特性,開發出來的 Actor 承載的業務邏輯太多,導致 Actor 的任務粒度過大,那么就很難發揮出 Actor 的最佳性能表現。

OK,在理解了這種并發框架的使用優勢之后,你可能仍然存在一個問題,就是究竟什么樣的業務系統會存在大量的并發信息交互,比較適合采用 Akka 并發框架呢?

按照我的實踐經驗,一般情況下,CPU 計算密集型的軟件系統會比較適合采用 Akka 并發框架。如果發現業務系統中存在大量基于并發消息隊列的通信,且核心業務都是圍繞著 CPU 計算邏輯,而 IO 請求并非核心業務邏輯,那么這樣的系統很可能比較適用 Akka 并發框架。實際上,很多種計算執行引擎就是比較典型的代表。比如,我之前開發的智能對話引擎,需要將多個計算模型的計算結果放在一起進行比較分析,它就非常適合采用 Akka 并發 Actor 框架模型。

不過,對于一些典型的互聯網微服務來說,當它們收到 REST 請求后,實現的核心業務邏輯主要是針對數據庫 CRUD 或是針對其他服務的 REST 接口調用,同時,這些不同的 REST 請求業務還是相對獨立的。那么,這類系統就應該屬于 IO 密集型業務,所以選擇采用 Akka 并發框架,往往優勢不是很大。

那么,針對 IO 密集型業務,選用線程池并發框架是不是就是性能最佳的方案呢?其實也不一定。下面我們就一起看下 Reactor 并發框架的實現特點,并了解下它在解決 IO 密集型業務時存在的優勢吧。

Reactor 響應式框架

Reactor 架構是一種基于數據流的響應式架構模式,嚴格來講它或許不能算是完整的并發框架,但卻內置了靈活調整并發的機制和能力。對于不太熟悉函數式編程范式的程序員而言,理解和使用 Reactor 架構可能會有些挑戰。不過沒關系,在今天的課程中,我會幫你弄清楚 Reactor 架構模型的基本原理和優勢,你不必受限于細節。當你在實際業務中需要決策是否使用這款并發框架時,再選擇深入學習具體的用法也不晚。

好,首先,我們一起來看看 Reactor 框架的工作原理圖。

圖片圖片

如上圖所示,輸入流 Flux 是 Reactor 中典型的異步消息流,它代表著一個包含 0 個到 N 個的消息序列。另外,圖中的 Rule 代表的是一個基于消息的處理邏輯或規則,輸入流中的消息可以被中間多個處理邏輯組合連續加工之后,再生成一個包含 0 個到 N 個的輸出消息流 Flux。

在看完原理圖之后,我們需要思考一個問題:Reactor 為什么要采用這樣的計算模型呢?它又能給軟件的性能帶來什么樣的優勢呢?其實,這里主要有兩個比較明顯的優勢,接下來我為你重點介紹。

第一個較大的性能優勢是它提供了背壓機制。通俗來講,就是圖中的中間處理規則(Rule)在接收處理消息時采用的是 Pull 模式,所以不存在數據消息積壓的情況。對于傳統的分布式并發系統而言,內部消息堆積是一個很普遍的影響性能的因素,而使用 Reactor 框架就可以避免這種情況發生。

第二個較大的性能優勢是在中間的消息處理規則實現中,針對 IO 的交互操作可以采用非阻塞的異步交互。在原來傳統的基于線程與 IO 交互的實現過程中,不管是使用直接的 IO 請求,還是基于 Future 的 get 機制,都不可避免地會發生當前線程被阻塞的情況。所以基于 Reactor 的異步響應式交互模式,在處理多 IO 請求時性能會更出色。

另外,在 Spring Boot 2.0 版本之后,也提供了對 Reactor 的全面支持,可以支持你去實現事件驅動模型的后端開發,從而更好地發揮軟件的性能優勢。

責任編輯:武曉燕 來源: 二進制跳動
相關推薦

2025-01-12 13:06:45

2023-11-20 22:44:09

Golang并發

2024-01-31 08:50:41

Guava并發工具

2019-07-18 11:08:09

Java并發框架

2024-11-04 09:22:54

2023-10-18 09:27:58

Java編程

2024-05-06 07:53:09

Go并發編程

2024-04-11 07:40:55

Go并發編程

2024-05-24 14:35:49

2017-08-04 11:41:53

Javathreadpool框架

2017-08-07 20:50:27

JavaForkJoin

2022-01-17 15:43:04

Go 并行性并發性

2024-12-16 17:00:00

并行并發Java

2021-11-10 15:18:16

JavaGo命令

2017-02-14 10:00:19

Java開發Lock

2012-08-08 09:32:26

C++多進程并發框架

2012-03-06 11:01:44

Java

2014-05-20 16:27:35

JVMScala

2010-08-26 12:53:40

CSSid選擇器

2010-08-10 13:15:30

IT認證課程秘訣
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久精品久久久久久 | 亚洲综合激情 | 日本在线中文 | 国产精品不卡视频 | 免费av手机在线观看 | 精品国产一区二区国模嫣然 | h片在线看| 国产区视频在线观看 | 91麻豆精品国产91久久久久久久久 | 国产精品久久久久久久久久免费看 | 午夜午夜精品一区二区三区文 | 中文字幕不卡一区 | 日韩成人一区二区 | 在线免费黄色 | 久久精品一二三影院 | 精品久久久久久久久久久久 | 日韩一级| 亚洲一区二区三区久久 | 色视频在线免费观看 | 一区二区福利视频 | 欧美精品一区二区免费视频 | 国产日韩视频在线 | 日本欧美国产在线观看 | 日日干天天干 | 日本在线中文 | 久久av影院 | 香蕉视频91| 日韩激情网| 国产午夜精品一区二区三区嫩草 | 国产精品久久久久久久久免费软件 | 国产精品永久 | 日韩成人免费中文字幕 | 97久久精品午夜一区二区 | 99久久免费观看 | 狠狠艹 | 色综合天天天天做夜夜夜夜做 | 免费在线一区二区 | 粉嫩国产精品一区二区在线观看 | 欧美中文字幕一区二区三区 | 久久精品国产一区二区电影 | 精彩视频一区二区三区 |