网站建设费用能否计入广告费sem竞价教程
文章目录
- 任务堆积导致 OOM(内存溢出)
- 问题描述
- 错误实现
- 正确实现
任务堆积导致 OOM(内存溢出)
问题描述
使用无界队列(如 LinkedBlockingQueue
)的线程池,在任务提交速率远高于处理速率时,队列无限堆积,最终导致内存溢出(OOM)。
错误实现
public class QueueOOMDemo {// 静态集合防止GC回收内存(加速OOM)private static final List<byte[]> memoryHolder = new ArrayList<>();public static void main(String[] args) {// 使用无界队列(快速堆积大对象)ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,new LinkedBlockingQueue<>());// 提交大量任务,每个任务分配2MB内存(加速内存消耗)for (int i = 0; i < 20000; i++) {executor.execute(() -> {// 分配2MB内存,并存入静态集合防止GC回收byte[] chunk = new byte[2 * 1024 * 1024];synchronized (memoryHolder) {memoryHolder.add(chunk);}// 模拟任务耗时try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}});}}
}
运行结果
Exception in thread "pool-1-thread-2" Exception in thread "pool-1-thread-3" Exception in thread "pool-1-thread-1" Exception in thread "pool-1-thread-4" Exception in thread "pool-1-thread-6" Exception in thread "pool-1-thread-5" Exception in thread "pool-1-thread-7" Exception in thread "pool-1-thread-8" java.lang.OutOfMemoryError: Java heap spaceat com.szkingdom.example.thread01.QueueOOMDemo.lambda$main$0(QueueOOMDemo.java:30)at com.szkingdom.example.thread01.QueueOOMDemo$$Lambda$1/897913732.run(Unknown Source)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)
Exception in thread "pool-1-thread-12" java.lang.OutOfMemoryError: Java heap space
Exception in thread "pool-1-thread-13" java.lang.OutOfMemoryError: Java heap space
问题分析
- 无界队列风险:默认队列容量为 `Integer.MAX_VALUE`,任务无限堆积,直至内存耗尽。
- OOM类型:通常为 `GC overhead limit exceeded` 或 `Java heap space`。
正确实现
- 限制队列容量:使用有界队列,防止任务无限堆积。
- 合理拒绝策略:任务满时触发拒绝策略,避免内存溢出。
public class QueueOOMFixedDemo {public static void main(String[] args) {// 使用有界队列(容量1000)和拒绝策略ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,new ArrayBlockingQueue<>(1000), // 队列容量1000new ThreadPoolExecutor.AbortPolicy());try {for (int i = 0; i < 20000; i++) {executor.execute(() -> {try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}});}} catch (RejectedExecutionException e) {System.err.println("任务被拒绝,已提交任务数:" + executor.getTaskCount());}executor.shutdown();}
}
运行结果
任务被拒绝,已提交任务数:1004