记一次jvm堆栈分析

程序如下:

@Slf4j
public abstract class XExecutor implements DataExecutor {
    private final Lock threadPoolLock = new ReentrantLock();
    @Override
    public boolean executor(List<DataRunnable> runnableList, int corePoolSize, int maxPoolSize, int capacity, String threadName) {
        try {
            threadPoolLock.lock();
            if (ThreadManager.pool.get() == null) {
                if (runnableList == null) {
                    throw new LocalRuntimeException("线程集合为空");
                }
//                if (runnableList.size() >= capacity) {
//                    throw new LocalRuntimeException("线程集合size:" + runnableList.size() + " > 线程池队列容量capacity:" + capacity);
//                }
                ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize,//核心池大小
                        maxPoolSize,//最大池大小
                        1000,//线程最大空闲时间,超过此空闲时间可以被收回
                        TimeUnit.MILLISECONDS, //最大空闲时间的单位
                        new ArrayBlockingQueue<>(capacity),//用于保存执行任务的队列,可以选择其他不同的队列来做任务管理
                        r -> new Thread(r, threadName + "-" + r.hashCode())
                );
                ThreadManager.pool.set(threadPool);
            }
            CountDownLatch countDownLatch = new CountDownLatch(runnableList.size());
            RunnableStatus runnableStatus = new RunnableStatus(countDownLatch);
            runnableList.forEach(runnable -> {
                runnable.setRunnableStatus(runnableStatus);
                ThreadManager.pool.get().submit(runnable);
            });
            //等待所有线程完毕
            ThreadManager.pool.get().shutdown();
            countDownLatch.await();
            this.remove(threadName);
            log.info("线程池执行完毕:{}", threadName);

            if (!runnableStatus.getExceptionList().isEmpty()) {
                runnableStatus.getExceptionList().forEach(e -> log.error("multi thread err,", e));
                return false;
            }
            return true;
        } catch (Exception e) {
            log.error("处理数据出现错误:", e);
           throw new RuntimeException("线程执行出现问题.....",e);
        } finally {
            threadPoolLock.unlock();
        }
        return false;
    }

使用jstack导出线程堆栈

jstack 16306 > jstack.tdump

使用jmap导出堆内存

jmap -dump:format=b,file=HeapDump.hprof 16306

使用VisualVM

在jdk的bin目录下,打开自带的jvisualVm工具
点击打开按钮
在这里插入图片描述

根据线程堆栈中

使用jvisualVm打开线程堆栈jstack.tdump
在这里插入图片描述
在堆栈中,找到如下信息
在这里插入图片描述
其中tid没有弄清楚是什么,有人说是线程栈的开始地址,貌似有道理。

在内存堆栈中,使用OQL查找对象

select heap.findObject(“0xf3800b58”)
在这里插入图片描述
点击对象连接,可以看到:
在这里插入图片描述
可以看到线程池中的两个执行线程,都在等待这个对象地址的锁

另外:介绍一个查找最消耗cpu的java线程,jps 找到java进程PID

命令:ps -mp p i d ∗ ∗ − o T H R E A D , t i d , t i m e 或 者 p s − L f p ∗ ∗ {pid}** -o THREAD,tid,time 或者 ps -Lfp ** pidoTHREAD,tid,timepsLfp{pid}

https://www.cnblogs.com/wangkangluo1/archive/2011/09/23/2185938.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值