2

簡単なシナリオ:

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を表示するにはどうすればよいですか? 私はそれをキャッチする必要がありますか?それは安全な操作でしょうか?

4

2 に答える 2

3

捕まえるべきではありませんErrors- それらはあなたのプログラムをうるさくクラッシュさせることを意図しています。Exceptionif aのみをキャッチする必要があります。あなたはそれを記録している/それを再スローしている、またはb. あなたはそれを処理しています。を処理する方法はないOutOfMemoryErrorので、プログラムをクラッシュさせてください。

「タスク完了」は、オブジェクトが作業を完了したときFutureではなく、オブジェクトが割り当てられたときに表示されます。f.get()各 Future を呼び出して、バイト配列の割り当てが完了したことを確認する必要があります。プロファイリング中はプログラムの実行が遅くなりFutures、Main メソッドが終了する前にバイト配列を割り当てることができるようになり、ヒープ領域をすべて使い果たすことができます。

f先物 (および ) の ArrayList に変更f = executor.submitf.add(executor.submit)、それを反復処理して.get()すべての先物を呼び出します。プロファイラーを使用せずに OutOfMemoryError をトリガーする必要があります。

于 2013-04-15T03:47:20.883 に答える
0

メイン スレッドは、スレッドによってスローされた例外を自動的に認識しません。例外をスローしない以前の実行方法が使用されたため、uncaughtexceptionhandler を使用せざるを得ませんでした。

JDK1.5 以降のフューチャと呼び出し可能オブジェクトが導入されました。callable の Call メソッドは値を返すだけでなく、例外をスローします。call メソッドによってスローされた例外をキャッチするには、future.get() を呼び出す必要があります。

したがって、コードは完全に機能しています。

于 2013-04-15T03:53:16.460 に答える