Java VisualVM 觀察自定義執行緒池
阿新 • • 發佈:2021-07-01
背景
在一次使用自定義執行緒池中,我發現了部分程式碼是用完沒有進行shutdown的,這樣是否會造成資源浪費?
一、首先我們把執行時時的執行緒數量打印出來,放上程式碼:然後開啟Java VisualVM進行觀測:
public class ThreadTest { public static void main(String[] args) throws Exception { AtomicInteger atomicInteger = new AtomicInteger(); for (int i = 0; i < 10; i++) { test(atomicInteger); } }public static void test(AtomicInteger atomicInteger) throws InterruptedException { //用於獲取到本java程序,進而獲取匯流排程數 RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); String jvmName = runtimeBean.getName(); System.out.println("JVM Name = " + jvmName); longpid = Long.valueOf(jvmName.split("@")[0]); System.out.println("JVM PID = " + pid); ThreadMXBean bean = ManagementFactory.getThreadMXBean(); int n = 3000000; for (int i = 0; i < n; i++) { ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 20, 1000, TimeUnit.SECONDS, newLinkedBlockingDeque<>()); for (int j = 0; j < 10; j++) { executor.execute(() -> { System.out.println(atomicInteger.getAndIncrement()+"==="+ Thread.currentThread().getName()+"==當前執行緒總數為:" + bean.getThreadCount()); }); }
// 此處控制是否釋放執行完執行緒 executor.shutdown(); } Thread.sleep(10000); System.out.println("執行緒總數為 = " + bean.getThreadCount()); } }
我們測試看看實際情況:
可以看到執行緒池有時候還沒來得及釋放的時候, 峰值是400多
非峰值很穩定在20多附近。
附上記憶體圖等情況:
第二次,因為如果不做執行緒睡眠,直接把服務幹掛了,連著visualVm都啟動不了, 我們程式碼需要調整下:
public class ThreadTest { public static void main(String[] args) throws Exception { AtomicInteger atomicInteger = new AtomicInteger(); for (int i = 0; i < 10; i++) { test(atomicInteger); } } public static void test(AtomicInteger atomicInteger) throws InterruptedException { //用於獲取到本java程序,進而獲取匯流排程數 RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); String jvmName = runtimeBean.getName(); System.out.println("JVM Name = " + jvmName); long pid = Long.valueOf(jvmName.split("@")[0]); System.out.println("JVM PID = " + pid); ThreadMXBean bean = ManagementFactory.getThreadMXBean(); int n = 3000000; for (int i = 0; i < n; i++) { ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 20, 1000, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); for (int j = 0; j < 10; j++) {
// 此處執行緒睡眠 Thread.sleep(500); executor.execute(() -> { System.out.println(atomicInteger.getAndIncrement()+"==="+ Thread.currentThread().getName()+"==當前執行緒總數為:" + bean.getThreadCount()); }); } // 此處控制執行緒執行完是否釋放 // executor.shutdown(); } Thread.sleep(10000); System.out.println("執行緒總數為 = " + bean.getThreadCount()); } }
調整後效果如下: 你發現執行緒數量永遠是網上升的
回收不了,已經越來越多了。
附上記憶體情況
三、結論
用完自定義執行緒池,一定要手動關閉shutDown掉池子