本章描述 Apache ActiveMQ Artemis 如何使用和彙集執行緒,以及您如何管理它們。

首先,我們將討論如何在伺服器端管理和使用執行緒,然後我們將探討用戶端。

1. 伺服器端執行緒管理

每個 Apache ActiveMQ Artemis 伺服器都維護一個用於一般用途的單一執行緒池,以及一個用於排程用途的排程執行緒池。Java 排程執行緒池無法設定為使用標準執行緒池,否則我們可以使用單一執行緒池來進行排程和非排程活動。

預設情況下,Apache ActiveMQ Artemis 將其執行緒池上限設定為 `Runtime.getRuntime().availableProcessors()` 所報告的核心(或超執行緒)數量的三倍,以處理傳入的封包。若要覆寫此值,您可以透過在傳輸組態中指定參數 nioRemotingThreads 來設定執行緒數。有關此方面的更多資訊,請參閱設定傳輸

還有少數其他地方直接使用執行緒,我們將依次討論每個地方。

1.1. 伺服器排程執行緒池

伺服器排程執行緒池用於伺服器端大多數需要定期或延遲執行的活動。它在內部對應到 java.util.concurrent.ScheduledThreadPoolExecutor 實例。

此池使用的最大執行緒數在 broker.xml 中使用 scheduled-thread-pool-max-size 參數設定。預設值為 5 個執行緒。此池通常只需要少數執行緒。

1.2. 一般用途伺服器執行緒池

此一般用途執行緒池用於伺服器端大多數非同步動作。它在內部對應到 java.util.concurrent.ThreadPoolExecutor 實例。

此池使用的最大執行緒數在 broker.xml 中使用 thread-pool-max-size 參數設定。

如果使用值 -1,則表示執行緒池沒有上限,並且在沒有足夠的執行緒可滿足請求的情況下,將按需建立新執行緒。如果稍後活動減少,則執行緒會逾時並關閉。

如果使用值 n,其中 n 是大於零的正整數,則表示執行緒池是有界的。如果有更多請求傳入,且池中沒有空閒執行緒且池已滿,則請求將被封鎖,直到有執行緒可用。建議謹慎使用有界執行緒池,因為如果選擇的上限過低,可能會導致死鎖情況。

thread-pool-max-size 的預設值為 30

有關無界(快取)和有界(固定)執行緒池的更多資訊,請參閱 J2SE javadoc

1.3. 過期清理執行緒

伺服器端還使用單一執行緒掃描佇列中過期的訊息。我們無法對此使用任何執行緒池,因為此執行緒需要以其自己的可設定優先權執行。

有關設定清理器的更多資訊,請參閱訊息過期

1.4. 非同步 IO

非同步 IO 具有一個執行緒池,用於接收和分派來自原生層的事件。您會在執行緒傾印中找到帶有前綴 ActiveMQ-AIO-poller-pool 的執行緒。Apache ActiveMQ Artemis 在日誌中每個開啟的檔案使用一個執行緒(通常有一個)。

還有一個單一執行緒用於在 libaio 上調用寫入。我們這樣做是為了避免 libaio 上的內容切換,否則會導致效能問題。您會在執行緒傾印中找到帶有前綴 ActiveMQ-AIO-writer-pool 的執行緒。

2. 用戶端執行緒管理

在用戶端,Apache ActiveMQ Artemis 維護一個單一的「全域」靜態排程執行緒池和一個單一的「全域」靜態一般執行緒池,供在該 JVM 實例中使用相同類別載入器的所有用戶端使用。

預設情況下,靜態排程執行緒池的最大大小為 5 個執行緒。可以使用 scheduledThreadPoolMaxSize URI 參數來變更此值。

一般用途執行緒池具有無上限的最大大小。可以使用 threadPoolMaxSize URL 參數來變更此值。

如果需要,也可以設定 Apache ActiveMQ Artemis,以便每個 ClientSessionFactory 實例不使用這些「全域」靜態池,而是維護自己的排程和一般用途池。從該 ClientSessionFactory 建立的任何工作階段都將改用這些池。這是使用 useGlobalPools 布林值 URL 參數設定的。