tomcat獲取執(zhí)行的線程池信息和線程堆棧的方法詳解
最近打算還是了解點java吧,搞點小demo。
想了解的知識點:
- 數(shù)據(jù)請求的堆棧,因為遇到過數(shù)據(jù)庫鎖表需要定位。(今天做點記錄,但有點不完美)
- 想得到數(shù)據(jù)庫連接沒釋放的那個線程堆棧。
- 找個access訪問記錄的排序工具類。
線程池信息獲取
- 線程池信息獲取或者告警可以用 dynamic-tp
- 獲取tomcat的線程信息可以用下面的代碼
//獲取webServer線程池 ThreadPoolExecutor executor = (ThreadPoolExecutor) ((TomcatWebServer) applicationContext.getWebServer()) .getTomcat() .getConnector() .getProtocolHandler() .getExecutor(); Map<String, String> returnMap = new LinkedHashMap<String, String>(); returnMap.put("核心線程數(shù)", String.valueOf(executor.getCorePoolSize())); returnMap.put("最大線程數(shù)", String.valueOf(executor.getMaximumPoolSize())); returnMap.put("活躍線程數(shù)", String.valueOf(executor.getActiveCount())); returnMap.put("池中當(dāng)前線程數(shù)", String.valueOf(executor.getPoolSize())); returnMap.put("歷史最大線程數(shù)", String.valueOf(executor.getLargestPoolSize())); returnMap.put("線程允許空閑時間/s", String.valueOf(executor.getKeepAliveTime(TimeUnit.SECONDS))); returnMap.put("核心線程數(shù)是否允許被回收", String.valueOf(executor.allowsCoreThreadTimeOut())); returnMap.put("提交任務(wù)總數(shù)", String.valueOf(executor.getSubmittedCount())); returnMap.put("歷史執(zhí)行任務(wù)的總數(shù)(近似值)", String.valueOf(executor.getTaskCount())); returnMap.put("歷史完成任務(wù)的總數(shù)(近似值)", String.valueOf(executor.getCompletedTaskCount())); returnMap.put("工作隊列任務(wù)數(shù)量", String.valueOf(executor.getQueue().size())); returnMap.put("拒絕策略", executor.getRejectedExecutionHandler().getClass().getSimpleName()); System.out.println(returnMap);
獲取tomcat的線程堆棧信息
首先需要了解下線程的狀態(tài):
1.NEW(創(chuàng)建)創(chuàng)建態(tài):當(dāng)一個已經(jīng)被創(chuàng)建的線程處于未被啟動時,即:還沒有調(diào)用start方法時,就處于這個狀態(tài)。
2.RUNNABLE(運行時)運行態(tài):當(dāng)線程已被占用,在Java虛擬機中正常執(zhí)行時,就處于此狀態(tài)。
3.BLOCKED(排隊時)阻塞態(tài):當(dāng)一個線程試圖獲取一個對象鎖,而該對象鎖被其他的線程持有,則該線程進入Blocked狀態(tài)。當(dāng)該線程持有鎖時,該線程將自動變成RUNNABLE狀態(tài)。
4.WAITING(休眠)休眠態(tài):一個線程在等待另一個線程執(zhí)行一個(喚醒)動作時,該線程進入Waiting狀態(tài)。進入這個狀態(tài)后是不能自動喚醒的,必須等待另一個線程調(diào)用notify或者notifyAll方法才能夠喚醒。
5.TIMED_WAITING (指定休眠時間)指定時間休眠態(tài):基本同WAITING狀態(tài),多了個超時參數(shù),調(diào)用對應(yīng)方法時線程將進入TIMED_WAITING狀態(tài),這一狀態(tài)將一直保持到超時期滿或者接收到喚醒通知,帶有超時參數(shù)的常用方法有Thread.sleep、鎖對象.wait() 。
6.TERMINATED (結(jié)束)結(jié)束態(tài):從RUNNABLE狀態(tài)正常退出而死亡,或者因為沒有捕獲的異常終止了RUNNABLE狀態(tài)而死亡。
系統(tǒng)啟動的線程有哪些
count:18 方法2:線程池的線程:Thread[Catalina-utility-1,1,main] 方法2:線程池的線程:Thread[Catalina-utility-2,1,main] 方法2:線程池的線程:Thread[container-0,5,main] 方法2:線程池的線程:Thread[File Watcher,5,main] 方法2:線程池的線程:Thread[Live Reload Server,5,main] -----------------名字包含了http 默認(rèn)初始10個線程 -----------------Acceptor線程主要用于監(jiān)聽套接字,將已連接套接字轉(zhuǎn)給Poller線程。 -----------------Poller線程主要用于以較少的資源輪詢已連接套接字以保持連接,當(dāng)數(shù)據(jù)可用時轉(zhuǎn)給工作線程。 方法2:線程池的線程:Thread[http-nio-0.0.0.0-8089-exec-1,5,main] 方法2:線程池的線程:Thread[http-nio-0.0.0.0-8089-exec-2,5,main] 方法2:線程池的線程:Thread[http-nio-0.0.0.0-8089-exec-3,5,main] 方法2:線程池的線程:Thread[http-nio-0.0.0.0-8089-exec-4,5,main] 方法2:線程池的線程:Thread[http-nio-0.0.0.0-8089-exec-5,5,main] 方法2:線程池的線程:Thread[http-nio-0.0.0.0-8089-exec-6,5,main] 方法2:線程池的線程:Thread[http-nio-0.0.0.0-8089-exec-7,5,main] 方法2:線程池的線程:Thread[http-nio-0.0.0.0-8089-exec-8,5,main] 方法2:線程池的線程:Thread[http-nio-0.0.0.0-8089-exec-9,5,main] 方法2:線程池的線程:Thread[http-nio-0.0.0.0-8089-exec-10,5,main] 方法2:線程池的線程:Thread[http-nio-0.0.0.0-8089-Poller,5,main] 方法2:線程池的線程:Thread[http-nio-0.0.0.0-8089-Acceptor,5,main] -------------------- 方法2:線程池的線程:Thread[DestroyJavaVM,5,main]
代碼
Thread mainThread = Thread.currentThread(); ThreadGroup mainThreadThreadGroup = mainThread.getThreadGroup(); //獲取線程組中的線程。 int count = mainThreadThreadGroup.activeCount(); System.out.println("count:"+count); Thread[] threads = new Thread[count]; //enumerate 枚舉,recurse 遞歸 mainThreadThreadGroup.enumerate(threads, true); Stream.of(threads).filter(Thread::isAlive).forEach(thread -> System.out.println("方法2:線程池的線程:" + thread ));
http的線程根據(jù)上面的信息
WAITING狀態(tài)的排除,名字做點過濾,去掉當(dāng)前線程,因為從上面得到的線程池不知道怎么得到線程,這里拿到所有做過濾。
Map<Thread, StackTraceElement[]> allThread = Thread.getAllStackTraces(); for (Thread t : allThread.keySet()) { /** * 一個線程可以在給定時間點處于一個狀態(tài)。 這些狀態(tài)是不反映任何操作系統(tǒng)線程狀態(tài)的虛擬機狀態(tài)。 * * 線程狀態(tài)。 線程可以處于以下狀態(tài)之一: * NEW 尚未啟動的線程處于此狀態(tài)。 * RUNNABLE 在Java虛擬機中執(zhí)行的線程處于此狀態(tài)。 * BLOCKED 被阻塞等待監(jiān)視器鎖定的線程處于此狀態(tài)。 * WAITING 正在等待另一個線程執(zhí)行特定動作的線程處于此狀態(tài)。 * TIMED_WAITING 正在等待另一個線程執(zhí)行動作達到指定等待時間的線程處于此狀態(tài)。 * TERMINATED 已退出的線程處于此狀態(tài)。 * */ StringBuilder sb=new StringBuilder(); if(!Thread.State.WAITING.equals(t.getState()) && t.getName().indexOf("http")>-1 && !Thread.currentThread().equals(t)) { System.out.println(t.getName()+":"+t.getState()); sb.setLength(0); for (StackTraceElement ele : t.getStackTrace()) { sb.append(ele.getClassName()).append(".").append(ele.getMethodName()).append(".").append(ele.getFileName()).append("$").append(ele.getLineNumber()).append("\n"); } System.out.println(sb.toString()); } }
測試
@RequestMapping(value = "/hello") public String testHello(Model model) throws InterruptedException { Thread.sleep(5000); model.addAttribute("currentTime", new Date()); return "hello"; } @RequestMapping(value = "/hello2") public String testHello2(Model model) throws InterruptedException { for(int i=0;i<Integer.MAX_VALUE;i++){ for(int j=0;j<Integer.MAX_VALUE;j++){} } model.addAttribute("currentTime", new Date()); return "hello"; }
以上就是tomcat獲取執(zhí)行的線程池信息和線程堆棧的方法詳解的詳細內(nèi)容,更多關(guān)于tomcat線程池信息和線程堆棧的資料請關(guān)注腳本之家其它相關(guān)文章!