2013-02-26 54 views
9

我在運行多個Java線程的應用程序中遇到了一些問題。 應用程序運行多個工作線程,在輸入隊列中持續查看,如果隊列中有消息,則將它們拉出並處理它們。CPU負載中的Java多線程

在這些工作線程中,還有另一個驗證線程計劃在固定的時間段執行一次檢查,以查看主機(運行應用程序的主機)是否仍然處於「良好狀態」以運行應用程序。此線程更新一個AtomicBoolean的值,然後在工作線程開始查看主機是否正常之前,該值被驗證。

我的問題是,在CPU負載過高的情況下,負責驗證的線程將花費更長時間,因爲它必須與所有其他線程競爭。如果AtomicBoolean在一段時間後沒有得到更新,它會自動設置爲false,導致我產生一個令人討厭的瓶頸。

我最初的方法是增加驗證線程的優先級,但更深入地挖掘它我發現這不是一個有保證的行爲,算法不應該依賴線程優先級來正確運行。

任何人有任何其他的想法嗎?謝謝!

+1

爲我們提供一些代碼 – Andremoniy 2013-02-26 14:23:18

+0

通常,優先級不應影響正常運行,但這似乎是一個優化問題。假設驗證線程的CPU負載較低,並且工作人員需要更多的CPU,請給予他們較低的優先級。此外,請確保您的原子的超時設置不會太低。 – 2013-02-26 14:27:18

+2

再次:向我們展示您的「驗證線程」的源代碼。 – Andremoniy 2013-02-26 14:47:38

回答

0

更多線程並不意味着更好的性能。通常情況下,如果你有雙核,2個線程提供最佳性能,3個或更多開始變差。四核心應該最好處理4個線程,所以要小心使用多少線程。

您可以讓其他線程在執行其工作後進入休眠狀態,並允許其他線程完成其工作。我相信Thread.yield()會暫停當前線程給其他線程。

如果你想讓你的線程連續運行,我會建議創建兩個主線程,線程A和B.使用A作爲驗證線程,並從B創建其他線程。因此線程A獲得更多的執行時間。

+0

我認爲,默認情況下,一個線程得到的是創建它的線程的優先級,所以在你描述用線程B創建的線程將具有與線程A相同的prio的情況下糾正我。如果我錯了,請糾正我 – 2013-02-26 14:53:04

+0

可能,我不確定,但我在這裏說的是,您繼續在線程A和B之間切換.B將需要運行多個線程,而A將是單個線程,因此A將獲得更多時間。根據優先級,我並不是指線程的優先級,我的意思是它會有更多的執行時間。讓我糾正一下,使其更清楚。 – Steve 2013-02-27 06:36:43

0

一種舊式的限制工作速度的方法,根本不使用健康檢查線程(並且繞過這些問題)是阻止或拒絕添加到隊列中的請求,如果隊列長於比方說100.這將動態反壓應用於生成負載的客戶端,並在工作線程超載時減慢它們的速度。

將此方法添加到Java 1.5庫中,請參閱java.util.concurrent.ArrayBlockingQueue。如果隊列已滿,put(o)方法會阻塞。

+0

不幸的是,我無法觸及隊列,因爲它們在限制範圍內 – 2013-02-26 14:50:41

0

是否使用Executor框架(來自Java的併發包)?如果不給它一個鏡頭。您可以嘗試使用ScheduledExecutorService作爲驗證線程。

+0

我實際上使用ScheduledThreadPoolExecutor作爲驗證線程。其他線程也使用ScheduledThreadPoolExecutor創建,但在不同的池中。這些線程執行的任務有一個while循環,所以它們連續執行。也許我錯過了一些東西。 – 2013-02-26 15:08:18

1

而是窺視到常規隊列中的數據結構,使用java.util.concurrent包的的LinkedBlockingQueue。

你可以做的是運行一個線程池(你可以使用執行服務的固定線程池,即你選擇的一些工作者)並且執行LinkedBlockingQueue.take()。

如果一條消息到達隊列,它將被送到一個等待線程(是的,take會阻塞線程,直到有東西被提供)。

Java API Reference for Linked Blocking Queue's take method

HTH。

+0

借調。不要只是在你的工作線程中旋轉和窺視,讓他們在一個鎖上等待()或在沒有任何事情時在隊列上阻塞。最有可能的情況是,您的活動過多的工作線程正在消除響應。正確地做。 – 2013-03-02 02:04:33