配置完 Idea 之后,接下来我们来实现一下业务代码。在代码中我们会创建一个大对象,这个对象中会有一个 10m 大的数组,然后我们将这个大对象存储在 ThreadLocal 中,再使用线程池执行大于 5 次添加任务,因为设置了最大运行内存是 50m,所以理想的情况是执行 5 次添加操作之后,就会出现内存溢出的问题,实现代码如下:
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; publicclass ThreadLocalOOMExample { /** * 定义一个 10m 大的类 */ staticclass MyTask { // 创建一个 10m 的数组(单位转换是 1M -> 1024KB -> 1024*1024B) privatebyte[] bytes = newbyte[10 * 1024 * 1024]; } // 定义 ThreadLocal privatestatic ThreadLocal<MyTask> taskThreadLocal = new ThreadLocal<>(); // 主测试代码 public static void main(String[] args) throws InterruptedException { // 创建线程池 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100)); // 执行 10 次调用 for (int i = 0; i < 10; i++) { // 执行任务 executeTask(threadPoolExecutor); Thread.sleep(1000); } } /** * 线程池执行任务 * @param threadPoolExecutor 线程池 */ private static void executeTask(ThreadPoolExecutor threadPoolExecutor) { // 执行任务 threadPoolExecutor.execute(new Runnable() { @Override public void run() { System.out.println("创建对象"); // 创建对象(10M) MyTask myTask = new MyTask(); // 存储 ThreadLocal taskThreadLocal.set(myTask); // 将对象设置为 null,表示此对象不在使用了 myTask = null; } }); } }
以上程序的执行结果如下:
从上述图片可看出,当程序执行到第 5 次添加对象时就出现内存溢出的问题了,这是因为设置了最大的运行内存是 50m,每次循环会占用 10m 的内存,加上程序启动会占用一定的内存,因此在执行到第 5 次添加任务时,就会出现内存溢出的问题。