• 在线程池中寻找堆栈


    在线程池中寻找堆栈

    下面看一个简单的例子:

    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实现内的信息,我们也知道了这个任务是在哪里提交的.

  • 相关阅读:
    [BZOJ1492][NOI2007]货币兑换Cash(斜率优化+CDQ分治)
    [P1768]天路(分数规划+SPFA判负环)
    [BZOJ5109][LOJ #6252][P4061][CodePlus 2017 11月赛]大吉大利,今晚吃鸡!(最短路+拓扑排序+传递闭包+map+bitset(hash+压位))
    [BZOJ1040][ZJOI2008]骑士(环套树dp)
    [P3759][TJOI2017]不勤劳的图书管理员(分块+树状数组)
    [CF665F]Four Divisors
    [LOJ6235]区间素数个数
    [SDOI2015]约数个数和
    [BZOJ3944]Sum
    [BZOJ2671]Calc
  • 原文地址:https://www.cnblogs.com/luozhiyun/p/9226843.html
Copyright © 2020-2023  润新知