该程序后期会不断 GC,但是又无法回收多少内存,最终可能会 OOM
import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor; import java.til.concurrent.TimeUnit; /** * 从数据库中读取信用数据,套用模型,并把结果进行记录和传输 */ public class T15_FullGC_Problem01 { private static class CardInfo { BigDecimal price = new BigDecimal(0.0); String name = "张三"; int age = 5; Date birthdate = new Date(); public void m() {} } private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(50, new ThreadPoolExecutor.DiscardOldestPolicy()); public static void main(String[] args) throws Exception { executor.setMaximumPoolSize(50); for (;;){ modelFit(); Thread.sleep(100); } } private static void modelFit(){ List<CardInfo> taskList = getAllCardInfo(); taskList.forEach(info -> { // do something executor.scheduleWithFixedDelay(() -> { //do sth with info info.m(); }, 2, 3, TimeUnit.SECONDS); }); } private static List<CardInfo> getAllCardInfo(){ List<CardInfo> taskList = new ArrayList<>(); for (int i = 0; i < 100; i++) { CardInfo ci = new CardInfo(); taskList.add(ci); } return taskList; } }
![]() | 1 senninha 2020-08-03 18:30:35 +08:00 CardInfo 一个都回收不了,这不就内存泄漏了。 |
2 ChanKc 2020-08-03 19:09:32 +08:00 via Android 一直都在加 cardinfo 而且 executor 来不及执行所以越来越多? |
![]() | 3 LudwigWS OP @senninha 请问一下为什么 CardInfo 回收不了?线程池满了以后旧的任务被抛弃了,按理说垃圾回收器不是能回收了么。 |
4 airfling 2020-08-03 19:36:12 +08:00 回收不了的,CardInfo 被 Runnable 隐式调用,ScheduledThreadPoolExecutor 你看的是核心线程是 50,但是任务队列应该是无线大的 |
5 yannxia 2020-08-03 19:46:11 +08:00 cardinfo 在 threadpool 的 queue 里面了,虽然都没有实际调用,但是的确是越来越多的。调整 scheduleWithFixedDelay 的速度 或者把 queue 改小。 |
![]() | 6 asd123456cxz 2020-08-03 20:09:08 +08:00 ScheduledThreadPoolExecutor 使用的是 DelayedWorkQueue,它在提交队列到容量上限时会进行扩容,即不会触发 discard 。 仅看了下源码,没有验证,有问题请指正 |