线程池的不规范使用导致的实例不gc问题

缘由

在开放提供的api中不规范使用了线程池,导致java堆中的线程实例不断增加,而线程池没有进行手动关闭的话是会一直保留线程的,故依赖的实例就会一直保留。

看代码

@Path("task")
public class XXXXRest extends BaseResourceApi {

    /**
     * 线程池大小
     */
    public static final int CORE_POOL_SIZE = 5;
    /**
     * 线程池最大数量
     */
    public static final int MAX__POOL_SIZE = 50;
    /**
     * 线程存活时间 ,单位秒
     */
    public static final long KEEP_ALIVE_TIME = 60L;

    /**
     * 处理定时任务使用线程池
     */
    private ExecutorService executorService =
        new ThreadPoolExecutor(CORE_POOL_SIZE, MAX__POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
    // 重点:在每个rest中创建了一个线程池,而并没有关闭线程池,导致线程池的实例会一直存在,而该实例依赖于rest,故rest实例也会一直存在
}

定位过程

  1. 使用jmap -dump:file=data.hprof pid当前状态下来,使用jvisualvm查看
    或者直接使用jvisualvm跟踪查看
  2. 查看该类的实例数量(第二行):jmap -histo pid | grep 类名

解决方案

将线程池设置为全局公用,这样就不会存在实例一直存在的问题了。

import org.springframework.stereotype.Component;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 公用线程池服务
 */
@Component
public class ExecutorSupport {
    private ExecutorService executorService = new ThreadPoolExecutor(50, 200, 60, TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(1000), new ThreadPoolExecutor.AbortPolicy());

    public void execute(Runnable runnable) {
        executorService.execute(runnable);
    }

    public Future submit(Callable callable) {
        return executorService.submit(callable);
    }
}

@Path("task")
public class XXXXRest extends BaseResourceApi {
    @Autowired
    private ExecutorSupport executorService;
}

复测

项目运行起来之后,使用jvisualvm确定实例是否为多个

jvisualvm的使用

在终端找到jvisualvm命令,运行在mac环境上,此时会出现画面,选择运行程序的pid连接进去。在监视一栏有个堆dump,点击即可产生heap信息。然后在heap信息页面上点击,在下方的输入框中输入要查找的类名,即可看见类的实例信息。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值