0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

怎么在JAVA中確定線性池大小

FPGA研究院 ? 來源:Java學(xué)研大本營 ? 2024-10-24 14:02 ? 次閱讀

JAVA中確定線性池大小,分別介紹CPU密集型任務(wù)和I/O密集型任務(wù)及其處理方法

在Java中,線程創(chuàng)建會產(chǎn)生顯著的開銷。創(chuàng)建線程會消耗時間,增加請求處理的延遲,并且涉及JVM和操作系統(tǒng)的相當(dāng)多工作。為減輕這些開銷,線程池應(yīng)運(yùn)而生。

線程池(ThreadPool)是由執(zhí)行器服務(wù)(executor service)管理的工作線程池。其理念是重用現(xiàn)有線程,而不是為每個任務(wù)創(chuàng)建新線程。這可以通過減少線程創(chuàng)建的開銷來顯著提高應(yīng)用程序的性能。Java的ExecutorService和ThreadPoolExecutor類提供了管理線程池的框架。

關(guān)鍵點

線程重用:線程池的線程可用于多個任務(wù)的重用。

任務(wù)排隊:任務(wù)被提交到池中,池中的線程會提取并執(zhí)行這些任務(wù)。

資源管理:可配置線程池大小、任務(wù)隊列大小和其他參數(shù),以高效管理資源。

1. 使用線性池的原因

性能:線程的創(chuàng)建和銷毀成本較高,尤其在Java中。創(chuàng)建一個可供多任務(wù)重用的線程池可減少這種開銷。

可擴(kuò)展性:線程池可根據(jù)應(yīng)用程序的需要進(jìn)行擴(kuò)展。例如,在負(fù)載較重時,可擴(kuò)展線程池以處理額外的任務(wù)。

資源管理:線程池可幫助管理線程使用資源。例如,線程池可限制同時活動的線程數(shù)量,防止應(yīng)用程序內(nèi)存不足。

2. 確定線程池大?。豪斫庀到y(tǒng)和資源限制

了解包括硬件和外部依賴關(guān)系的系統(tǒng)限制,對于確定線程池大小至關(guān)重要。下面通過一個例子來詳細(xì)說明這一概念。

假設(shè)在開發(fā)一個處理傳入HTTP請求的Web應(yīng)用程序,每個請求可能涉及數(shù)據(jù)庫處理數(shù)據(jù)和調(diào)用外部第三方服務(wù)。目標(biāo)是確定處理這些請求的最佳線程池大小。

此情況下需考慮因素包含數(shù)據(jù)庫連接池與外部服務(wù)吞吐量兩方面。

數(shù)據(jù)庫連接池:假設(shè)使用HikariCP之類的連接池來管理數(shù)據(jù)庫連接。您已將其配置為允許最多100個連接。如果您創(chuàng)建的線程超過可用連接數(shù),這些額外的線程將會等待可用連接,導(dǎo)致資源爭用和潛在的性能問題。

以下是配置HikariCP數(shù)據(jù)庫連接池的示例。

importcom.zaxxer.hikari.HikariConfig;
importcom.zaxxer.hikari.HikariDataSource;

publicclassDatabaseConnectionExample{
publicstaticvoidmain(String[]args){
HikariConfigconfig=newHikariConfig();
config.setJdbcUrl("jdbc//localhost:3306/mydb");
config.setUsername("username");
config.setPassword("password");
config.setMaximumPoolSize(100);//設(shè)置最大連接數(shù)

HikariDataSourcedataSource=newHikariDataSource(config);

//使用 dataSource 獲取數(shù)據(jù)庫連接并執(zhí)行查詢。
}
}

外部服務(wù)吞吐量:此應(yīng)用程序交互的外部服務(wù)有一個限制。它一次只能處理少量請求,例如10個請求。并發(fā)更多請求可能會使服務(wù)不堪重負(fù),導(dǎo)致性能下降或出現(xiàn)錯誤。CPU核心確定服務(wù)器上可用的CPU核心數(shù)量對于優(yōu)化線程池大小至關(guān)重要。

intnumOfCores=Runtime.getRuntime().availableProcessors();

每個核心可以同時執(zhí)行一個線程。超出CPU核心數(shù)量的線程會導(dǎo)致過度的上下文切換,從而降低性能。

3.CPU密集型任務(wù)與I/O密集型任務(wù)

CPU密集型任務(wù)

CPU密集型任務(wù)是那些需要大量處理能力的任務(wù),例如執(zhí)行復(fù)雜計算或運(yùn)行模擬。這些任務(wù)通常受限于CPU的速度,而不是I/O設(shè)備的速度,如下列任務(wù)。

編碼或解碼音頻視頻文件

編譯和鏈接軟件

運(yùn)行復(fù)雜模擬

執(zhí)行機(jī)器學(xué)習(xí)或數(shù)據(jù)挖掘任務(wù)

玩視頻游戲

要對CPU密集型任務(wù)進(jìn)行優(yōu)化,應(yīng)考慮多線程和并行性。并行處理是一種技術(shù),用于將較大的任務(wù)劃分為較小的子任務(wù),并將這些子任務(wù)分配到多個CPU核心或處理器上,以利用并發(fā)執(zhí)行并提高整體性能。假設(shè)有一個大型數(shù)字?jǐn)?shù)組,要使用多個線程并發(fā)計算每個數(shù)字的平方,以利用并行處理,示例代碼如下。

importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
importjava.util.concurrent.TimeUnit;

publicclassParallelSquareCalculator{
publicstaticvoidmain(String[]args){
int[]numbers={1,2,3,4,5,6,7,8,9,10};
intnumThreads=Runtime.getRuntime().availableProcessors();//獲取CPU核心數(shù)量
ExecutorServiceexecutorService=Executors.newFixedThreadPool(numThreads);

for(intnumber:numbers){
executorService.submit(()->{
intsquare=calculateSquare(number);
System.out.println("Squareof"+number+"is"+square);
});
}

executorService.shutdown();
try{
executorService.awaitTermination(Long.MAX_VALUE,TimeUnit.NANOSECONDS);
}catch(InterruptedExceptione){
Thread.currentThread().interrupt();
}
}

privatestaticintcalculateSquare(intnumber){
//模擬耗時計算(例如,數(shù)據(jù)庫查詢、復(fù)雜計算)
try{
Thread.sleep(1000);//模擬1秒延遲
}catch(InterruptedExceptione){
Thread.currentThread().interrupt();
}

returnnumber*number;
}
}

I/O密集型任務(wù)

I/O密集型任務(wù)是那些與存儲設(shè)備(例如,讀寫文件)、網(wǎng)絡(luò)套接字(例如API調(diào)用)或用戶輸入進(jìn)行交互(例如圖形用戶界面的交互)的任務(wù),下面是一些典型的I/O密集型任務(wù)。

讀取或?qū)懭氪笪募酱疟P(例如,保存視頻文件、加載數(shù)據(jù)庫)

通過網(wǎng)絡(luò)下載或上傳文件(例如,瀏覽網(wǎng)頁、觀看流媒體視頻)

發(fā)送和接收電子郵件

運(yùn)行Web服務(wù)器或其他網(wǎng)絡(luò)服務(wù)

執(zhí)行數(shù)據(jù)庫查詢

Web服務(wù)器處理傳入請求

優(yōu)化I/O密集型任務(wù)的方式

在內(nèi)存中緩存頻繁訪問的數(shù)據(jù),以減少重復(fù)I/O操作的需要。

負(fù)載均衡,將I/O密集型任務(wù)分配到多個線程或進(jìn)程中,以高效處理并發(fā)I/O操作。

使用SSD,固態(tài)硬盤(SSDs)相較于傳統(tǒng)硬盤(HDDs)可以顯著加快I/O操作。

使用高效數(shù)據(jù)結(jié)構(gòu),如哈希表和B樹,以減少所需的I/O操作次數(shù)。

避免不必要的文件操作,例如多次打開和關(guān)閉文件。

4.在兩種任務(wù)中確定線程數(shù)

確定CPU密集型任務(wù)的線程數(shù)量

對于CPU密集型任務(wù),要最大化CPU利用率,而不讓系統(tǒng)因線程過多而超負(fù)荷,防止過度的上下文切換。一個常見方法是使用可用CPU核心數(shù)量。假設(shè)需開發(fā)一個視頻處理應(yīng)用程序。視頻編碼是一項CPU密集型任務(wù),需要應(yīng)用復(fù)雜算法來壓縮視頻文件。有一個多核CPU可用。

計算可用CPU核心:使用Runtime.getRuntime().availableProcessors()確定可用的CPU核心數(shù)量。假設(shè)有8個核心。

創(chuàng)建線程池:創(chuàng)建一個大小接近或略少于可用CPU核心數(shù)量的線程池。在這種情況下,您可以選擇6或7個線程,以便為其他任務(wù)和系統(tǒng)進(jìn)程留出一些CPU容量。

importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;

publicclassVideoEncodingApp{
publicstaticvoidmain(String[]args){
intavailableCores=Runtime.getRuntime().availableProcessors();
intnumberOfThreads=Math.max(availableCores-1,1);//根據(jù)需要進(jìn)行調(diào)整

ExecutorServicethreadPool=Executors.newFixedThreadPool(numberOfThreads);

//將視頻編碼任務(wù)提交到線程池。
for(inti=0;i{
encodeVideo();//模擬視頻編碼任務(wù)
});
}

threadPool.shutdown();
}

privatestaticvoidencodeVideo(){
//模擬視頻編碼(CPU 密集型)任務(wù)。
//這里進(jìn)行復(fù)雜計算和壓縮算法。
}
}

確定I/O密集型任務(wù)的線程數(shù)量

對于I/O密集型任務(wù),最佳線程數(shù)通常由I/O操作的性質(zhì)和預(yù)期延遲決定。您希望擁有足夠的線程以保持I/O設(shè)備繁忙而不使其過載。理想的數(shù)量不必等于CPU核心的數(shù)量??紤]構(gòu)建一個網(wǎng)頁爬蟲,下載網(wǎng)頁并提取信息。這涉及HTTP請求,這是因網(wǎng)絡(luò)延遲引起的I/O密集型任務(wù),可從如下兩方面進(jìn)行分析。

分析I/O延遲:估計預(yù)期的I/O延遲,這依賴于網(wǎng)絡(luò)或存儲。例如,如果每個 HTTP 請求大約需要500毫秒完成,您可能需要考慮I/O操作中的一些重疊。

創(chuàng)建線程池:創(chuàng)建一個大小平衡并行性與預(yù)期I/O延遲的線程池。您不一定需要為每個任務(wù)分配一個線程;相反,可以有一個較小的池,能夠高效管理I/O密集型任務(wù)。

以下是網(wǎng)頁爬蟲的示例代碼。

importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;

publicclassWebPageCrawler{
publicstaticvoidmain(String[]args){
intexpectedIOLatency=500;//估計的I/O延遲(毫秒)
intnumberOfThreads=4;//根據(jù)預(yù)期延遲和系統(tǒng)能力進(jìn)行調(diào)整

ExecutorServicethreadPool=Executors.newFixedThreadPool(numberOfThreads);

//要抓取的 URL 列表。
String[]urlsToCrawl={
"https://example.com",
"https://google.com",
"https://github.com",
//在這里添加更多URL
};

for(Stringurl:urlsToCrawl){
threadPool.execute(()->{
crawlWebPage(url,expectedIOLatency);
});
}

threadPool.shutdown();
}

privatestaticvoidcrawlWebPage(Stringurl,intexpectedIOLatency){
//模擬網(wǎng)頁抓取(I/O 密集型)任務(wù)。
//執(zhí)行 HTTP 請求并處理頁面內(nèi)容。
try{
Thread.sleep(expectedIOLatency);//模擬I/O延遲
}catch(InterruptedExceptione){
Thread.currentThread().interrupt();
}
}
}

5.總結(jié)公式

確定線程池大小的公式可以寫成如下形式。

線程數(shù)=可用核心數(shù)*目標(biāo)CPU利用率*(1+等待時間/服務(wù)時間)

該公式各部分的詳細(xì)解釋如下。

可用核心數(shù):這是您的應(yīng)用程序可用的 CPU 核心數(shù)量。重要的是要注意,這與 CPU 的數(shù)量不同,因為每個 CPU 可能有多個核心。

目標(biāo)CPU利用率:這是您希望應(yīng)用程序使用的 CPU 時間的百分比。如果將目標(biāo)CPU利用率設(shè)置得過高,應(yīng)用程序可能會變得無響應(yīng);如果設(shè)置得太低,應(yīng)用程序?qū)o法充分利用可用CPU資源。

等待時間:這是線程等待I/O操作完成的時間。這可能包括等待網(wǎng)絡(luò)響應(yīng)、數(shù)據(jù)庫查詢或文件操作的時間。

服務(wù)時間:這是線程執(zhí)行計算的時間。

阻塞系數(shù):這是等待時間與服務(wù)時間的比率。它是衡量線程在 I/O 操作完成之前等待的時間相對于執(zhí)行計算時間的比例。

示例使用

假設(shè)有一個具有4個CPU核心的服務(wù)器,并且希望應(yīng)用程序使用50%的可用 CPU資源。

您的應(yīng)用程序有兩個任務(wù)類別:I/O密集型任務(wù)和CPU密集型任務(wù)。

I/O密集型任務(wù)的阻塞系數(shù)為0.5,意味著它們花費(fèi)50%的時間等待I/O 操作完成。

線程數(shù)=4核心*0.5*(1+0.5)=3線程

CPU 密集型任務(wù)的阻塞系數(shù)為 0.1,意味著它們花費(fèi) 10% 的時間等待 I/O 操作完成。

線程數(shù)=4核心*0.5*(1+0.1)=2.2線程

此示例創(chuàng)建了兩個線程池,一個用于I/O密集型任務(wù),一個用于CPU密集型任務(wù)。I/O密集型線程池將有3個線程,CPU密集型線程池將有2個線程。

來源: 本文轉(zhuǎn)載自Java學(xué)研大本營公眾號

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    10780

    瀏覽量

    210498
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    6620

    瀏覽量

    123044
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2948

    瀏覽量

    104375
  • 線程池
    +關(guān)注

    關(guān)注

    0

    文章

    56

    瀏覽量

    6820

原文標(biāo)題:如何正確判斷Java線程池的大小

文章出處:【微信號:FPGA研究院,微信公眾號:FPGA研究院】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    Java的線程包括哪些

    線程是用來統(tǒng)一管理線程的, Java 創(chuàng)建和銷毀線程都是一件消耗資源的事情,線程可以重復(fù)使用線程,不再頻繁的創(chuàng)建、銷毀線程。 初識
    的頭像 發(fā)表于 10-11 15:33 ?762次閱讀
    <b class='flag-5'>Java</b><b class='flag-5'>中</b>的線程<b class='flag-5'>池</b>包括哪些

    USB八口MODEM USB八口MODEM USB八口短信MODEM Q2406A

    MODEM WAVECOM Q24Plus短信貓二次開發(fā)專家(DELPHI/ASP/PB/VB/VC/C#/JAVA/ 中間件數(shù)據(jù)庫接口)16口短信MODEM 八口MODEM U
    發(fā)表于 10-30 18:08

    USB八口MODEM USB八口MODEM

    MODEM WAVECOM Q24Plus短信貓二次開發(fā)專家(DELPHI/ASP/PB/VB/VC/C#/JAVA/ 中間件數(shù)據(jù)庫接口)16口短信MODEM 八口MODEM U
    發(fā)表于 06-28 15:28

    請問keep out畫線確定板子大小是按坐標(biāo)來確定線的長度的嗎?

    大家keep out畫線確定板子大小,是按坐標(biāo)來確定線的長度的嗎?有沒有更好的方法?
    發(fā)表于 04-22 22:52

    如何確定SPI FlashFPGA配置的大小

    伙計們,我的電路板提供了FPGA處于硬復(fù)位狀態(tài)時讀取SPI閃存的能力(這種能力獨(dú)立于FPGA;可以說是“側(cè)讀”)。假設(shè)我有一個具有有效FPGA配置的SPI Flash。如何確定SPI Flash
    發(fā)表于 06-09 13:28

    內(nèi)存可以調(diào)節(jié)內(nèi)存的大小

    嵌入式–內(nèi)存直接上代碼,自己體會。嵌入式設(shè)備,一般keil提供的堆很小,一般都不使用。使用內(nèi)存,自己可以調(diào)節(jié)內(nèi)存大小。頭文件 malloc.h#ifndef __MALLOC_H#define
    發(fā)表于 12-17 07:00

    關(guān)于RT-Thread內(nèi)存管理的內(nèi)存簡析

    連接起來。分配內(nèi)存塊。在用戶申請內(nèi)存塊時,從空閑鏈表取出第一個內(nèi)存塊給申請者。內(nèi)存工作機(jī)制如下圖所示。注意:內(nèi)存一旦創(chuàng)建并初始化完成后,其內(nèi)部的內(nèi)存塊大小就固定了,不能再做調(diào)整。
    發(fā)表于 04-06 17:02

    java 常量靜態(tài)變量詳解

    Java的常量,實際上分為兩種形態(tài):靜態(tài)常量和運(yùn)行時常量。 所謂靜態(tài)常量,即*.cla
    發(fā)表于 09-27 13:01 ?10次下載
    <b class='flag-5'>java</b> 常量<b class='flag-5'>池</b>靜態(tài)變量詳解

    數(shù)據(jù)庫連接的設(shè)置怎么確定大小

    數(shù)據(jù)庫連接的配置是開發(fā)者們常常搞出坑的地方,配置數(shù)據(jù)庫連接時,有幾個可以說是和直覺背道而馳的原則需要明確。
    的頭像 發(fā)表于 05-04 14:23 ?2691次閱讀
    數(shù)據(jù)庫連接<b class='flag-5'>池</b>的設(shè)置怎么<b class='flag-5'>確定</b><b class='flag-5'>大小</b>

    HK-MR340系列:用于確定腫瘤的大小和位置

    醫(yī)學(xué)治療過程想要確定腫瘤的大小和位置,但苦于缺乏互補(bǔ)的線性位置反饋?同時又想要在檢測過程
    的頭像 發(fā)表于 08-31 16:48 ?828次閱讀
    HK-MR340系列:用于<b class='flag-5'>確定</b>腫瘤的<b class='flag-5'>大小</b>和位置

    Java線程核心原理

    看過Java線程源碼的小伙伴都知道,Java線程池中最核心的類就是ThreadPoolExecutor,
    的頭像 發(fā)表于 04-21 10:24 ?797次閱讀

    【虹科新品】HK-MR340系列:用于確定腫瘤的大小和位置

    HK-MR340系列用于確定腫瘤的大小和位置簡介在醫(yī)學(xué)治療過程想要確定腫瘤的大小和位置,但苦于缺乏互補(bǔ)的
    的頭像 發(fā)表于 09-01 15:13 ?558次閱讀
    【虹科新品】HK-MR340系列:用于<b class='flag-5'>確定</b>腫瘤的<b class='flag-5'>大小</b>和位置

    JSF業(yè)務(wù)線程大小配置用例說明

    JSF 業(yè)務(wù)線程使用 JDK 的線程技術(shù),缺省情況下采用 Cached 模式(核心線程數(shù) 20,最大線程數(shù) 200)。此外,還提供了 Fixed 固定線程大小的模式,兩種模式均可設(shè)置請求隊列
    的頭像 發(fā)表于 09-19 11:15 ?771次閱讀

    化技術(shù)的應(yīng)用實踐

    作為一名Java開發(fā)人員,化技術(shù)或多或少在業(yè)務(wù)代碼中使用。常見的包括線程、連接等。也是因為Java語言超級豐富的基建,基本上這些
    的頭像 發(fā)表于 11-24 10:22 ?454次閱讀
    <b class='flag-5'>池</b>化技術(shù)的應(yīng)用實踐

    線程的運(yùn)轉(zhuǎn)流程圖 化技術(shù)實踐案例解析

    作為一名Java開發(fā)人員,化技術(shù)或多或少在業(yè)務(wù)代碼中使用。常見的包括線程、連接等。也是因為Java語言超級豐富的基建,基本上這些
    的頭像 發(fā)表于 11-24 10:22 ?408次閱讀
    線程<b class='flag-5'>池</b>的運(yùn)轉(zhuǎn)流程圖 <b class='flag-5'>池</b>化技術(shù)實踐案例解析