• 在线程池中寻找堆栈


    在线程池中寻找堆栈

    下面看一个简单的例子:

    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) {
            ThreadPoolExecutor pools = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                    0L, TimeUnit.SECONDS,
                    new SynchronousQueue<Runnable>());
    
            for (int i = 0; i < 5; i++) {
                pools.submit(new DivTask(100, i));
            }
        }
    

    可以得到:

    100.0
    25.0
    33.0
    50.0
    

    只有4个输出,也就是说程序漏算了一组数据,并且程序没有任何日志,没有任何错误提示.

    解决上述问题最简单的一种方法就输出放弃submit(),改用execute()

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

    或者使用

    Future  submit = pools.submit(new DivTask(100, i));
    submit.get();
    

    上面两种方法都可以得到部分堆栈信息,如下所示:

    Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
    	at threadDemo.DivTask.run(DivTask.java:19)
    	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
    

    这里只能知道异常是在哪里抛的,并不知道是在哪里提交的,所以我们扩展我们的ThreadPoolExecutor线程池

    /**
     * @author luozhiyun on 2018/6/25.
     */
    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 command) {
            super.execute(wrap(command,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 clientStack, String clientThreadName) {
            return new Runnable() {
                @Override
                public void run() {
                    try {
                        task.run();
                    } catch (Exception e) {
                        clientStack.printStackTrace();
                        throw e;
                    }
                }
            };
        }
    
        public static void main(String[] args) {
            ThreadPoolExecutor pools = new TraceThreadPoolExecutor(0, Integer.MAX_VALUE,
                    0L, TimeUnit.SECONDS,
                    new SynchronousQueue<Runnable>());
    
            for (int i = 0; i < 5; i++) {
                pools.execute(new DivTask(100, i));
            }
        }
    }
    

    通过上面扩展的线程池, 就可以打印出堆栈信息了

    100.0
    25.0
    33.0
    50.0
    java.lang.Exception: Client stack trace
    	at threadDemo.TraceThreadPoolExecutor.clientTrace(TraceThreadPoolExecutor.java:25)
    	at threadDemo.TraceThreadPoolExecutor.execute(TraceThreadPoolExecutor.java:16)
    	at threadDemo.TraceThreadPoolExecutor.main(TraceThreadPoolExecutor.java:48)
    Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
    	at threadDemo.DivTask.run(DivTask.java:19)
    	at threadDemo.TraceThreadPoolExecutor$1.run(TraceThreadPoolExecutor.java:33)
    	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)
    
    Process finished with exit code 0
    
    

    现在我们不仅可以得到异常发生的Runnable实现内的信息,我们也知道了这个任务是在哪里提交的.

  • 相关阅读:
    【转载】mysql dual 虚拟表
    Mysql中DATE_SUB函数
    mybatis中<include>标签的作用
    IDEA提升幸福感的小技巧之"快速从controller跳转到serviceImpl"
    MySQL一些常用的时间函数 current_timestamp()
    SpringCloud配置中心搭建与使用(本地存储配置)
    Linux内存管理 (7)VMA操作【转】
    linux下的调试工具ltrace与strace【转】
    (十四)Linux内存管理之page fault处理【转】
    Linux系统调用详解(实现机制分析)--linux内核剖析(六)【转】
  • 原文地址:https://www.cnblogs.com/luozhiyun/p/9226843.html
Copyright © 2020-2023  润新知