java - 为什么当 Future 抛出这个 OutOfMemoryError 时没有出现?

标签 java concurrency out-of-memory

一个简单的场景:

private static final ExecutorService executor =
        Executors.newCachedThreadPool();

public static void main(String... args) throws InterruptedException, ExecutionException {
    Future<byte[]> f = null;
    for (int i = 0; i < 10; i++) {
        f = executor.submit(new Callable<byte[]>(){
            @Override
            public byte[] call() {
                System.out.println("Starting task.");
                try {
                    return new byte[1500 * 1024 * 1024];    // 1500 mb
                }
                finally {
                    System.out.println("Task complete.");
                }
            }
        });
    }
//  System.out.println(f.get().length);
}

当我运行上面的代码时,它(据称)运行时没有错误。

(奇怪的是,当我在 NetBeans 中分析此代码时,会抛出 OutOfMemoryError 错误,但正常运行时则不会。)

所有 10 个“任务已完成。”消息立即显示,但时间范围对于实际分配字节数组来说太短了。

当我取消注释最后一行时,会抛出ExecutionException

我知道代码示例有点荒谬...... 但为什么根本没有抛出异常,我怎样才能让 OutOfMemoryError 显示出来呢?我必须捕获它吗?这样操作安全吗?

最佳答案

您不应该捕获错误 - 它们的目的是让您的程序崩溃。您应该仅在以下情况下捕获 Exception:你正在记录它/重新抛出它或者b。你正在处理它;您无法处理 OutOfMemoryError,所以让它像预期那样使您的程序崩溃。

“任务完成”是在分配了 Future 对象时显示的,而不是在它们完成工作时显示的 - 您需要调用 f.get() 在每个 Future 上确保它完成了字节数组的分配。当您对其进行分析时,程序运行速度会变慢,这允许更多的Futures在Main方法终止之前分配它们的字节数组,这反过来又允许它们用完您的所有堆空间。 p>

f 更改为 futures 的 ArrayList(并将 f = executor.submit 更改为 f.add(executor.submit)),然后迭代它并对其所有 future 调用 .get() 。这应该会在不使用探查器的情况下触发您的 OutOfMemoryError。

关于java - 为什么当 Future 抛出这个 OutOfMemoryError 时没有出现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16007345/

相关文章:

java - N+1 HTTP 调用通过同时队列进行批处理

java - 单独的 Java 线程中的 OutOfMemoryError

java - 使用 Apache POI 在 Java 中将 .doc 转换为 .html

java - 在java中,有没有办法在线程进入等待状态而不是完成时将其设为 "Join"?

使用 join() 的 Java 多线程程序在计算相邻数字之和时给出了错误的结果

sql - INSERT 或 SELECT 策略总是返回一行?

java - 垃圾收集器是否保证在内存不足错误之前运行?

android - 运行时异常、view.InflateException、reflection.InvocationTargetException 和 OutOfMemoryError

java - 由于命名空间错误而导致 ActivityNotFoundException?

Java 时间段(十进制年数)