zoukankan      html  css  js  c++  java
  • 在线程池中寻找堆栈

    在线程池中寻找堆栈

    下面看一个简单的例子:

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

  • 相关阅读:
    ZR#330. 【18 提高 3】矿石(容斥)
    牛客NOIP提高组R1 C保护(主席树)
    BZOJ1026: [SCOI2009]windy数(数位dp)
    AtCoderBeginnerContest109题解
    BZOJ3679: 数字之积(数位dp)
    牛客NOIP普及组R1 C括号(dp)
    牛客NOIP提高组R1 A中位数(二分)
    BZOJ1576: [Usaco2009 Jan]安全路经Travel(最短路 并查集)
    ZRDay6A. 萌新拆塔(三进制状压dp)
    Python 入门教程 10 ---- Student Becomes the Teacher
  • 原文地址:https://www.cnblogs.com/luozhiyun/p/9226843.html
Copyright © 2011-2022 走看看