好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

打印Java程序的线程栈信息方式

打印Java程序的线程栈信息

jstack可以得知当前线程的运行情况

安装jstack等命令集,jstack是开发版本jdk的一部分,不是开发版的有可能找不到

?

1

yum install -y  java- 1.8 . 0 -openjdk-devel

查看要打印堆栈的java进程ID

?

1

jps -l

打印堆栈

?

1

sudo -u admin jstack pid  > jstack.txt

特别要注意的是jstack需要使用与进程一致的用户才能正确导出堆栈,否则会报错如下

Unable to open socket file: target process not responding or HotSpot VM not loaded

线程池异常堆栈的坑

?

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

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

import java.util.concurrent.*;

public class DivTask implements Runnable{

     int a,b;

     public DivTask( int a, int b) {

         this .a = a;

         this .b = b;

     }

     @Override

     public void run() {

         double re = a/b;

         System.out.println(re);

     }

     public static void main(String[] args) throws InterruptedException, ExecutionException {

//        ThreadPoolExecutor executor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 0L, TimeUnit.SECONDS

//                , new SynchronousQueue<>());

         TraceThreadPoolExecutor executor = new TraceThreadPoolExecutor( 0 , Integer.MAX_VALUE, 0L, TimeUnit.SECONDS

                 , new SynchronousQueue<>());  //扩展TraceThreadPoolExecutor

         for ( int i = 0 ; i < 5 ; i++) {

             // executor.submit(new DivTask(100,i));

             //改进方式一:

             //Future re = executor.submit(new DivTask(100, i));

             //re.get();

             //改进方式二:

             executor.execute( new DivTask( 100 ,i));

         }

         //100.0

         //25.0

         //33.0

         //50.0

         //其中100/0的异常结果没打印

         //线程池很有可能"吃掉程序抛出的异常

         //改进方式一:

         //Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero

         //  at java.util.concurrent.FutureTask.report(FutureTask.java:122)

         //  at java.util.concurrent.FutureTask.get(FutureTask.java:192)

         //。。。

         //改进方式二:

         //Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero

         //  at com.Test.DivTask.run(DivTask.java:15)

         //  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)

         //  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)

         //  at java.lang.Thread.run(Thread.java:748)

         //100.0

         //33.0

         //25.0

         //50.0

         //扩展TraceThreadPoolExecutor

         //java.lang.Exception: Client stack trace

         //  at com.Test.TraceThreadPoolExecutor.clientTrace(TraceThreadPoolExecutor.java:20)

         //  at com.Test.TraceThreadPoolExecutor.execute(TraceThreadPoolExecutor.java:12)

         //  at com.Test.DivTask.main(DivTask.java:29)

         //Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero

         //  at com.Test.DivTask.run(DivTask.java:15)

         //  at com.Test.TraceThreadPoolExecutor.lambda$wrap$0(TraceThreadPoolExecutor.java:25)

         //  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)

         //  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)

         //  at java.lang.Thread.run(Thread.java:748)

         //100.0

         //25.0

         //33.0

         //50.0

     }

}

?

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

26

27

28

29

30

import java.util.concurrent.*;

/**

  * 扩展TraceThreadPoolExecutor,让它在调度任务前先保存一下提交任务线程的堆栈信息

  */

public class TraceThreadPoolExecutor extends ThreadPoolExecutor {

     public TraceThreadPoolExecutor( int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {

         super (corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);

     }

     @Override

     public void execute(Runnable task) {

         super .execute(wrap(task,clientTrace(),Thread.currentThread().getName()));

     }

     @Override

     public Future<?> submit(Runnable task) {

         return super .submit(wrap(task,clientTrace(),Thread.currentThread().getName()));

     }

     private Exception clientTrace(){

         return new Exception( "Client stack trace" );

     }

     private Runnable wrap( final Runnable task, final Exception clientTrace,String clientThreadName){

         return () -> {

             try {

                 task.run();

             } catch (Exception e) {

                 clientTrace.printStackTrace();

                 throw e;

             }

         };

     }

}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/x356982611/article/details/96147628

查看更多关于打印Java程序的线程栈信息方式的详细内容...

  阅读:29次