在线程池中寻找堆栈

在线程池中寻找堆栈

下面看一个简单的例子:

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

原文地址:https://www.cnblogs.com/luozhiyun/p/9226843.html

时间: 2024-08-30 06:23:01

在线程池中寻找堆栈的相关文章

Java线程池中线程的状态简介

首先明确一下线程在JVM中的各个状态(JavaCore文件中) 1.死锁,Deadlock(重点关注) 2.执行中,Runnable(重点关注) 3.等待资源,Waiting on condition(重点关注) 4.等待监控器检查资源,Waiting on monitor(eg:如果使用System.out.println等需要分配计算机资源的时候线程会如此等待,主要还需看堆栈) 5.暂停,Suspended 6.对象等待中,Object.wait() 7.阻塞,Blocked(重点关注) 8

线程池中的线程的排序问题

1 package org.zln.thread.poolqueue; 2 3 import org.slf4j.Logger; 4 import org.slf4j.LoggerFactory; 5 6 import java.util.Comparator; 7 import java.util.UUID; 8 import java.util.concurrent.*; 9 10 /** 11 * 线程池中的线程的排序问题 12 * Created by sherry on 16/11/4

多线程篇七:通过Callable和Future获取线程池中单个务完成后的结果

使用场景:如果需要拿到线程的结果,或者在线程完成后做其他操作,可以使用Callable 和 Futrue 1.定义一个线程池,向线程池中提交单个callable任务 ExecutorService threadPools=Executors.newSingleThreadExecutor(); Future<String> future=threadPools.submit(new Callable<String>() { @Override public String call(

C#如何判断线程池中所有的线程是否已经完成之Demo

1 start: 2 3 System.Threading.RegisteredWaitHandle rhw = null; 4 new Action(() => 5 { 6 for (var i = 0; i < 30; i++) { 7 new Action<int>((index) => 8 { 9 System.Threading.Thread.Sleep(1000); 10 Console.WriteLine(System.Threading.Thread.Curr

C#如何判断线程池中所有的线程是否已经完成(转)

其 实很简单用ThreadPool.RegisterWaitForSingleObject方法注册一个定时检查线程池的方法,在检查线程的方法内调用 ThreadPool.GetAvailableThreads与ThreadPool.GetMaxThreads并比较两个方法返回的值是不是相等, 相等表示线池内所有的线程已经完成. //每秒检次一次线程池的状态 RegisteredWaitHandle rhw = ThreadPool.RegisterWaitForSingleObject(Auto

JAVA线程池中队列与池大小的关系

JAVA线程中对于线程池(ThreadPoolExecutor)中队列,池大小,核心线程的关系写出自己的理解: 1:核心线程:简单来讲就是线程池中能否允许同时并发运行的线程的数量 2:线程池大小:线程池中最多能够容纳的线程的数量. 3:队列:对提交过来的任务的处理模式. 对于线程池与队列的交互有个原则: 如果队列发过来的任务,发现线程池中正在运行的线程的数量小于核心线程,则立即创建新的线程,无需进入队列等待.如果正在运行的线程等于或者大于核心线程,则必须参考提交的任务能否加入队列中去. 1:提交

Thread 线程池中可用的线程数量

GetAvaliableThread(out workerThreadCount,out iocompletedThreadCount)   函数居然一次返回了两个变量.线程池里的线程按照公用被分成了两大类:工作线程和IO线程,或者IO完成线程,前者用于执行普通的操作,后者专用于异步IO,比如文件和网络请求,注意,分类并不说明两种线程本身有差别,线程就是线程,是一种执行单元,从本质上来讲都是一样的,线程池这样分类 Thread 线程池中可用的线程数量

通过实验研究“线程池中线程数目的变化规律” --- 下有不错的线程池使用 原理 总结

通过实验研究“线程池中线程数目的变化规律” 自从看了老赵关于线程池的实验以后,我就想学着做一个类似的实验,验证自己的理解,现在终于做好了,请大家指正. 一般情况下我们都使用Thread类创建线程,因为通过Thread对象可以对线程进行灵活的控制.但创建线程和销毁线程代价不菲,过多的线程会消耗掉大量的内存和CPU资源,假如某段时间内突然爆发了100个短小的线程,创建和销毁这些线程就会消耗很多时间,可能比线程本身运行的时间还长.为了改善这种状况,.NET提供了一种称之为线程池(Thread Pool

原 线程池中shutdown()和shutdownNow()方法的区别

参考:shutdown和shutdownNow的区别 shutDown() 当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态.此时,则不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常.但是,此时线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出. shutdownNow() 根据JDK文档描述,大致意思是:执行该方法,线程池的状态立刻变成STOP状态,并试图停止所有正在执行的线程,不再处理还在池队列中等待的任务,