线程池OOM错误

1、LinkedBlockingQueue报错

package com.spring.pro.threadpool.completableFuture.youhua.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import lombok.extern.slf4j.Slf4j;

/**
 * @Title: ExecutorsDemo.java
 * @ProjectName com.spring.pro.threadpool
 * @Description:
 * @author ybwei
 * @date 2020年1月3日 下午7:26:22
 */
@Slf4j
public class ThreadPoolTest {

	public static void main(String[] args) {
		ExecutorService executor = Executors.newFixedThreadPool(5);
		for (int i = 0; i < Integer.MAX_VALUE; i++) {
			executor.execute(() -> {
				try {
					TimeUnit.SECONDS.sleep(1);
				} catch (InterruptedException e) {
					log.info("线程错误:", e);
				}
			});
		}
	}
}

JVM参数-Xmx5m -Xms5m

线程池OOM错误_第1张图片

异常:

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
	at java.util.concurrent.LinkedBlockingQueue.offer(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.execute(Unknown Source)
	at com.spring.pro.threadpool.completableFuture.youhua.test.ThreadPoolTest.main(ThreadPoolTest.java:22)

OOM描述:

JVM抛出 java.lang.OutOfMemoryError: GC overhead limit exceeded 错误就是发出了这样的信号: 执行垃圾收集的时间比例太大, 有效的运算量太小. 默认情况下, 如果GC花费的时间超过 98%, 并且GC回收的内存少于 2%, JVM就会抛出这个错误。

OOM原因:

newFixedThreadPool中创建的LinkedBlockingQueue,是无界队列。不断向队列添加任务就会导致内存溢出。

2、ArrayBlockingQueue报错

上面的例子只是造成OOM的一个demo,实际上

package com.spring.pro.threadpool.completableFuture.test;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import lombok.extern.slf4j.Slf4j;

/**
 * @Title: CompletableFutureTest.java
 * @ProjectName com.spring.pro.threadpool
 * @Description:
 * @author ybwei
 * @date 2020年1月3日 下午4:29:25
 */
@Slf4j
public class CompletableFutureTest {

	public static void main(String[] args) throws InterruptedException, ExecutionException {
		ArrayBlockingQueue arrayWorkQueue = new ArrayBlockingQueue<>(400000);
		ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, // corePoolSize线程池中核心线程数
				10, // maximumPoolSize 线程池中最大线程数
				60, // 线程池中线程的最大空闲时间,超过这个时间空闲线程将被回收
				TimeUnit.SECONDS, // 时间单位
				// 下面是采用有界队列和无界队列的区别
				arrayWorkQueue,
				// linkedWorkQueue,

				// 下面是jdk的四种执行策略
				// new ThreadPoolExecutor.AbortPolicy() 这种策略直接抛出异常,丢弃任务。
				// new ThreadPoolExecutor.DiscardPolicy() 这种策略和AbortPolicy几乎一样,也是丢弃任务,只不过他不抛出异常。
				new ThreadPoolExecutor.CallerRunsPolicy() // 线程调用运行该任务的 execute,调用者运行者
		// 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。没看明白,当时是我的main线程执行的task5
//				new ThreadPoolExecutor.DiscardOldestPolicy()// 如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)
		);
		
		log.info("线程开始");
		handle(threadPool);
		log.info("线程结束");
	}

	/**  
	 * @Description: 
	 * @param threadPool
	 * @Author: ybwei
	 * @Date: 2020年1月3日 下午7:43:56
	 */ 
	private static void handle(ThreadPoolExecutor threadPool) {
		for(int i=0;i {
				try {
					log.info("运行开始");
					TimeUnit.SECONDS.sleep(10);
					log.info("运行结束");
				} catch (InterruptedException e) {
				}
				log.info("run end ...");
			},threadPool);
		}
	}
}

JVM参数-Xmx5m -Xms5m,依然会报OOM。因为队列太长了new ArrayBlockingQueue<>(400000)。

 

你可能感兴趣的:(多线程,java)