簡體   English   中英

為Java RIA客戶端應用程序配置線程池的最佳方法

[英]Best way to configure a Threadpool for a Java RIA client app

我有一個Java客戶端,它通過HTTP訪問我們的服務器端,發出幾個小請求來加載每個新的數據頁。 我們維護一個線程池來處理所有非UI處理,因此所有后台客戶端任務以及所有想要與服務器建立連接的任務。 我一直在研究一些性能問題,但不確定我們是否已盡可能完善線程池。 當前,我們使用核心池大小為8的ThreadPoolExecutor,對工作隊列使用LinkedBlockingQueue,因此最大池大小將被忽略。 毫無疑問,在所有情況下都無法簡單地做到這一點,但有沒有最佳實踐。 我目前的想法是

1)我將切換為使用SynchronousQueue而不是LinkedBlockingQueue,以便使池可以增長到最大池大小。 2)我將最大池大小設置為無限制。

基本上,我當前的擔心是,由於線程池大小的上限,服務器端偶爾出現的性能問題會導致無關的客戶端處理停止。 我擔心無止境地管理客戶端上的那些線程會帶來額外的損失,可能只是兩種弊端中的一種。

有什么建議,最佳做法或有用的參考資料嗎? 干杯,羅賓

通常,網絡延遲很容易比客戶端上的內存分配或線程管理方面可能發生的任何事情高幾個數量級。 因此,通常來說,如果您遇到性能瓶頸,請首先關注網絡鏈接。

如果問題在於您的服務器根本無法跟上客戶端的請求,那么增加客戶端的線程數量將無濟於事:您只需等待8個線程來獲得對更多請求的響應就可以了線程正在等待(由於正在管理的連接數量增加,甚至可能由於增加服務器負載而加劇服務器端問題)。

JDK中的兩個並發隊列都是高性能的。 選擇實際上歸結為用法語義。 如果您有非阻塞管道,則使用非阻塞隊列更為自然。 如果您不這樣做,那么使用阻塞隊列更有意義。 (您始終可以將Integer.MAX_VALUE指定為限制)。 如果不需要FIFO處理,請確保您未指定合理的順序,因為這將對性能造成重大影響。

聽起來您可能最好限制隊列大小:當有許多請求排隊時,您的應用程序是否仍能正常運行(將所有任務長時間排隊是否可以接受,對其他任務來說更重要)? 如果仍然有排隊的任務並且用戶退出應用程序,會發生什么情況? 如果隊列變得非常大,那么服務器是否有可能趕上(足夠快的時間)完全向用戶隱藏問題?

我想為需要更新其用戶界面響應的請求創建一個隊列,並使其隊列保持很小。 如果此隊列太大,請通知用戶。

對於實際的后台任務,請保留一個單獨的池,該池具有更長的隊列,但不是無限的。 當該池增長時或當用戶想要退出但仍有任務時,為該池定義優美的行為,應該怎么辦?

正如alphazero所說,如果您遇到瓶頸,則無論使用哪種方法,客戶端等待作業的數量都會繼續增長。

真正的問題是您要如何處理瓶頸。 或更正確地說,是您希望用戶如何處理瓶頸。

如果使用無限制的隊列,則不會收到有關瓶頸已發生的反饋。 在某些應用程序中,這很好:如果用戶啟動異步任務,則無需報告積壓(假定最終清除了該積壓)。 但是,如果用戶在執行下一個客戶端任務之前需要等待響應,這是非常糟糕的。

如果在有界隊列上使用LinkedBlockingQueue.offer() ,那么您將立即得到一個響應,指出隊列已滿,並且可以采取措施,例如禁用某些應用程序功能,彈出對話框等。 但是,這將需要您做更多的工作,特別是如果可以從多個地方提交請求的話。 我建議,如果還沒有,請在服務器隊列上創建一個GUI感知層,以提供常見的行為。

而且,當然,永遠不要從事件線程中調用LinkedBlockingQueue.put() (除非您不介意掛起的客戶端)。

為什么不創建無界隊列,而是在隊列達到一定大小時拒絕任務(甚至可能通知用戶服務器正忙(取決於應用程序!))? 然后,您可以記錄此事件並找出在服務器端發生了什么事以進行備份。此外,除非您要連接到多個遠程服務器,否則池中只有幾個線程可能沒有什么意義,盡管這確實取決於您的應用程序,它的功能以及與誰交談。

擁有無限制的池通常很危險,因為它通常不會正常降級。 最好記錄問題,發出警報,防止進一步的操作排隊,並弄清楚如何擴展服務器端(如果存在問題),以防止再次發生這種情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM