0

私の Java Web アプリには、約 200 通のメールを送信するメソッドがあります。メール サーバーの遅延のため、プロセス全体に約 7 分かかります。この一括メール送信は、ユーザー アクションの結果として発生する必要があります。もちろん、ユーザーが次に転送されるまでそれほど長く待つ必要はありません。とにかくApacheがタイムアウトすることは言うまでもありません。そのため、FutureTaskを実装して、処理中にプロセスを別のスレッドで実行しようとしています残りのコードは次のようになります。

Some code;

Runnable r = (Runnable)new sendEmails(ids);
FutureTask task = new FutureTask(r, null);
Thread t = new Thread(task);
t.start();

Some more code;

ただし、アプリは FutureTask が完了するのを待ってから続行します。これは、スクリプトの残りの部分を続行しながら、サイドで別のスレッドでコードを実行する最良の方法ではないという考えにオープンです。より良い方法はありますか/これを機能させるにはどうすればよいですか?

4

1 に答える 1

0

for ループで 200 以上のスレッドをスピンアップしているようです。これはマシンに大きな負荷をかけ、各スレッドに割り当てられる各スタックのサイズにより、JVM がメモリ不足になる前にあまり多くのスレッドを必要としないため、最初は多くの GC と JVM がロックアップし、その後潜在的に十分な負荷がかかると、クラッシュします。

悲しいことに、コードが FutureTask の完了を待っている理由を説明できる場合とできない場合があります。非常に多くのスレッドを作成/スケジュールすることによって、スラッシングが発生するのを待っているように見えるだけかもしれません。しかし、そうではないかもしれません。上記のスニペットから切り取られたコードを同期する何かが他にある可能性が非常に高いです。

どこかに隠れているトリッキーな同期があるかどうかを見つける方法は、コードの実行中に ctrl-break を押すことです (コマンド ラインから実行していると仮定すると、intellij/eclipse の両方に便利なスタック ダンプ アイコンがあります)。これにより、システム内のすべてのスレッドのスタック ダンプが表示されます。これにより、将来のタスクが完了するのを待っているユーザー スレッドを見つけることができ、どのモニターで待機しているかがわかります。待機していない場合は、別の問題があります。たとえば、システムが短時間で非常に多くのスレッドを作成してスラッシングするため、短時間でロックアップしたように見えます。

しかし、最初に、問題を隠している可能性があるため、過度のスレッド作成部分を避けます。次のようなコードを使用することをお勧めします。

ExecutorService scheduler = Executors.newCachedThreadPool() 
scheduler.submit( task )
于 2013-03-01T19:19:45.567 に答える