3 回答

TA貢獻1942條經驗 獲得超3個贊
即使異常名稱強烈建議也不是內存問題,而是操作系統資源問題。您用完了本機線程,即操作系統將允許您的JVM使用多少線程。
這是一個不常見的問題,因為您很少需要那么多。您是否有很多無條件線程產生,這些線程應該在哪里出現但未完成?
您可能會考慮盡可能在執行器的控制下重寫為使用Callable / Runnables。有許多行為可以由您的代碼輕松控制的標準執行程序。
(有許多原因限制了線程數,但是它們因操作系統而異)

TA貢獻1906條經驗 獲得超3個贊
在負載測試期間遇到了相同的問題,原因是由于JVM無法進一步創建新的Java線程。以下是JVM源代碼
if (native_thread->osthread() == NULL) {
// No one should hold a reference to the 'native_thread'.
delete native_thread;
if (JvmtiExport::should_post_resource_exhausted()) {
JvmtiExport::post_resource_exhausted(
JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR |
JVMTI_RESOURCE_EXHAUSTED_THREADS,
"unable to create new native thread");
} THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "unable to create new native thread");
} Thread::start(native_thread);`
根本原因:當JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR(資源耗盡(意味著內存耗盡))或JVMTI_RESOURCE_EXHAUSTED_THREADS(線程耗盡)時,JVM引發此異常。
在我的情況下,Jboss創建了太多線程來滿足請求,但是所有線程都被阻塞了。因此,JVM耗盡了線程和內存(每個線程都保存了memory,因為每個線程都被阻塞,所以不釋放內存)。
分析Java線程轉儲后,發現有將近61K線程被我們的方法之一阻塞,這導致了此問題。以下是線程轉儲的一部分
"SimpleAsyncTaskExecutor-16562" #38070 prio=5 os_prio=0 tid=0x00007f9985440000 nid=0x2ca6 waiting for monitor entry [0x00007f9d58c2d000]
java.lang.Thread.State: BLOCKED (on object monitor)

TA貢獻2011條經驗 獲得超2個贊
您的操作系統可能不允許您嘗試創建的線程數,或者您在JVM中達到了一定的限制。特別是如果它是一個32k的整數,則很可能是一種或另一種限制。
您確定您確實需要32k線程嗎?大多數現代語言都對可重用線程池提供了某種支持-我確定Java也已經具備了一些功能(例如ExecutorService
,如用戶Jesper所述)。也許您可以從這樣的池中請求線程,而不是手動創建新線程。
添加回答
舉報