java獲取狀態
A. java線程池中線程的狀態
探討Java線程池中線程的狀態,我們首先聚焦於ThreadPoolExecutor的內部實現。ThreadPoolExecutor#runWorker方法是線程執行任務的核心代碼。
運行過程中,ThreadPoolExecutor#getTask方法負責從任務隊列中獲取任務。若獲取結果為null,線程將退出循環嘗試退出當前Worker。
對於提問者關注的這部分代碼,關鍵在於理解getTask方法的循環邏輯,以及其返回null的兩種情況。
第一種情況涉及ThreadPoolExecutor的shutdown和shutdownNow方法,通過區分這兩種狀態,可以清晰理解其工作邏輯。
第二種情況則聚焦於boolean timed = allowCoreThreadTimeOut || wc > corePoolSize的判斷。這個變數與核心線程是否允許超時相關聯,進而影響後續邏輯處理。
最後,我們關注不返回null的代碼部分。對於LinkedBlockingQueue,其take和poll操作會調用AbstractQueuedSynchronizer.ConditionObject的await和awaitNanos方法,再調用LockSupport的park和parkNanos方法,最終通過Unsafe類的park方法實現線程的阻塞。
B. java 如何獲得一個進程的內存使用情況,cpu運行的時間
首先有個基本問題需要了解一下:
這里所說java里獲得一個進程的內存使用情況和cpu運行時間,是指在java內部獲取一個純外部進程的內存與cpu時間呢,還是指在java內部,由java啟動的進程的內存與cpu時間。
如果是第一種情況,那你還需要在java內部再起一個進程,通過執行操作系統的shell命令來查看那個進程的運行狀態。比如那個外部進程的ID為3119,則執行cat /proc/3119/status | grep VmRSS就可以過濾出該進程的物理內存佔用量。
如果是第二種情況,(假定你問的就是這種情況)。
先說內存佔用量:一般說來,你可以使用這兩種方式獲取內存使用情況
方式一:
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
MemoryUsage memoryUsage = memoryMXBean.getHeapMemoryUsage(); //椎內存使用情況
long totalMemorySize = memoryUsage.getInit(); //初始的總內存
long maxMemorySize = memoryUsage.getMax(); //最大可用內存
long usedMemorySize = memoryUsage.getUsed(); //已使用的內存
方式二:
Runtime rt = Runtime.getRuntime();
long totalMemorySize = rt.totalMemory(); //初始的總內存
long maxMemorySiz = t.maxMemory(); //最大可用內存
long freeMemorySize = rt.freeMemory(); //當前可用內存
需要說明的是,這種方式獲取的是整個jvm的內存使用情況,並不是某一個進程的內存使用情況,事實上,在java內部,可以使用Rumtime.getRuntime().exec(${SHELL})來開啟一個外部進程(這里${SHELL}代表一個可操作系統的shell命令)。而運行Java程序整個jvm,對於操作系統而言,也僅僅只是一個進程。也就是說,一個jvm就是一個進程,你通過java程序開啟的進程都是外部進程,java內部目前還提供了一個destroy方法來銷毀該進程,對於該進程的其它信息,都無法直接獲取,這些信息的獲取,顯然需要本地化(Local)的實現。既然標准jdk庫沒有,就不可能再通過平台無關的代碼來實現了。典型的做法就是使用前面第一種情況的方式,再啟一個進程,執行shell命令來獲取。
不過對於cpu使用時間,採用標准java代碼倒是可以拿到。由於java的語法很啰嗦,舉一個較完全的例子需要太多的代碼,我這里就只寫最關鍵的代碼:
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
① long currentCpuTime = threadMXBean.getCurrentThreadCpuTime(); //當前線程的cpu使用時間
long someThreadId = 709817L; //假定有某個線程的ID是709817
② long someThreadCpuTime = threadMXBean.getThreadCpuTime(someThreadId); //獲取ID為someThreadId即709817的線程的cpu時間
基於上面的核心api,你可以把由java啟動的外部進程放到一個單獨的線程中執行,再用代碼②的方式來獲取該進程的cpu使用時間,也可以將外部進程放入到當前線程中執行,用① 的方式來獲得進程的cpu使用時間。