原因
ScheduledThreadPoolExecutor继承自ThreadPoolExecutor,而前者构造方法调用的是后者的构造方法,而且maximumPoolSize值为Integer.MAX_VALUE,这会导致缓冲队列中存在过多任务对象没有被处理并回收内存。
demo
@Test
public void main() {
int coreThreadCount = 1;
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("test-pool-%d").build();
RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
Thread1 th = (Thread1)r;
System.out.println("任务被拒绝:" + th.id + ",将不执行此任务");
}
};
AtomicLong id = new AtomicLong(0);
ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(coreThreadCount, threadFactory, rejectedExecutionHandler);
while (true) {
System.out.println("发起任务:" + id.get());
// 为了更快地触发OOM,延时1小时才执行任务
scheduledExecutorService.scheduleAtFixedRate(new Thread1(id.getAndIncrement()), 1, 1, TimeUnit.HOURS);
}
}
class Thread1 implements Runnable {
// 创建耗内存的数组,便于触发OOM
private long[] arr = new long[1024*1024];
private long id;
public Thread1(long id) {
this.id = id;
}
@Override
public void run() {
try {
Thread.sleep(1000 * 60*60*24);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程 "+ id +" 在运行");
}
}
运行结果:
发起任务:0
发起任务:1
发起任务:2
...(省略3-210)
发起任务:211
发起任务:212
java.lang.OutOfMemoryError: Java heap space
at com.sqlu.learn.threadpool.ScheduledExecutorServiceTest$Thread1.<init>(ScheduledExecutorServiceTest.java:49)
at com.sqlu.learn.threadpool.ScheduledExecutorServiceTest.main(ScheduledExecutorServiceTest.java:36)