最近打算还是了解点java吧,搞点小demo。
想了解的知识点:
- 数据请求的堆栈,因为遇到过数据库锁表需要定位。(今天做点记录,但有点不完美)
- 想得到数据库连接没释放的那个线程堆栈。
- 找个access访问记录的排序工具类。
线程池信息获取
- 线程池信息获取或者告警可以用 dynamic-tp
- 获取tomcat的线程信息可以用下面的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | //获取webServer线程池 ThreadPoolExecutor executor = (ThreadPoolExecutor) ((TomcatWebServer) applicationContext.getWebServer()) .getTomcat() .getConnector() .getProtocolHandler() .getExecutor(); Map returnMap = new LinkedHashMap(); returnMap.put( "核心线程数" , String.valueOf(executor.getCorePoolSize())); returnMap.put( "最大线程数" , String.valueOf(executor.getMaximumPoolSize())); returnMap.put( "活跃线程数" , String.valueOf(executor.getActiveCount())); returnMap.put( "池中当前线程数" , String.valueOf(executor.getPoolSize())); returnMap.put( "历史最大线程数" , String.valueOf(executor.getLargestPoolSize())); returnMap.put( "线程允许空闲时间/s" , String.valueOf(executor.getKeepAliveTime(TimeUnit.SECONDS))); returnMap.put( "核心线程数是否允许被回收" , String.valueOf(executor.allowsCoreThreadTimeOut())); returnMap.put( "提交任务总数" , String.valueOf(executor.getSubmittedCount())); returnMap.put( "历史执行任务的总数(近似值)" , String.valueOf(executor.getTaskCount())); returnMap.put( "历史完成任务的总数(近似值)" , String.valueOf(executor.getCompletedTaskCount())); returnMap.put( "工作队列任务数量" , String.valueOf(executor.getQueue().size())); returnMap.put( "拒绝策略" , executor.getRejectedExecutionHandler().getClass().getSimpleName()); System.out.println(returnMap); |
获取tomcat的线程堆栈信息
首先需要了解下线程的状态:
1.NEW(创建)创建态:当一个已经被创建的线程处于未被启动时,即:还没有调用start方法时,就处于这个状态。
2.RUNNABLE(运行时)运行态:当线程已被占用,在Java虚拟机中正常执行时,就处于此状态。
3.BLOCKED(排队时)阻塞态:当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态。当该线程持有锁时,该线程将自动变成RUNNABLE状态。
4.WAITING(休眠)休眠态:一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。
5.TIMED_WAITING (指定休眠时间)指定时间休眠态:基本同WAITING状态,多了个超时参数,调用对应方法时线程将进入TIMED_WAITING状态,这一状态将一直保持到超时期满或者接收到唤醒通知,带有超时参数的常用方法有Thread.sleep、锁对象.wait() 。
6.TERMINATED (结束)结束态:从RUNNABLE状态正常退出而死亡,或者因为没有捕获的异常终止了RUNNABLE状态而死亡。
系统启动的线程有哪些
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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 默认初始 10 个线程 -----------------Acceptor线程主要用于监听套接字,将已连接套接字转给Poller线程。 -----------------Poller线程主要用于以较少的资源轮询已连接套接字以保持连接,当数据可用时转给工作线程。 方法 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] |
代码
1 2 3 4 5 6 7 8 9 | 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的线程根据上面的信息
WAITING状态的排除,名字做点过滤,去掉当前线程,因为从上面得到的线程池不知道怎么得到线程,这里拿到所有做过滤。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | Map allThread = Thread.getAllStackTraces(); for (Thread t : allThread.keySet()) { /** * 一个线程可以在给定时间点处于一个状态。 这些状态是不反映任何操作系统线程状态的虚拟机状态。 * * 线程状态。 线程可以处于以下状态之一: * NEW 尚未启动的线程处于此状态。 * RUNNABLE 在Java虚拟机中执行的线程处于此状态。 * BLOCKED 被阻塞等待监视器锁定的线程处于此状态。 * WAITING 正在等待另一个线程执行特定动作的线程处于此状态。 * TIMED_WAITING 正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。 * TERMINATED 已退出的线程处于此状态。 * */ 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()); } } |
测试
1 2 3 4 5 6 7 8 9 10 | @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 |
以上就是tomcat获取执行的线程池信息和线程堆栈的方法详解的详细内容,更多关于tomcat线程池信息和线程堆栈的资料请关注IT俱乐部其它相关文章!