0

run メソッドを持つクラスがあり、そのクラスのメイン メソッドのタイマーは、次のコードでクラスを呼び出しています。

Timer timer = new Timer();
timer.scheduleAtFixedRate(new LegacySmsSender(), 0, 2*1000);

run メソッドで、ThreadExecutorPool を宣言します。

ThreadPoolExecutor packetProcessorThreadPool =
        new ThreadPoolExecutor(4,
                                4,
                                Long.MAX_VALUE,
                                TimeUnit.DAYS,
                                new LinkedBlockingQueue<Runnable>(),
                                new MyThreadFactory("packetProcessorThreadPool")
                                );

私は4つのPacketProcessorを作成しnew PacketProcessor()、 それらのリターンをリストにpacketProcessorThreadPool.submit保持します。Future次に、それらすべてがループで終了するのを待ちます。

for(Future<?> f:packetProcessorList)
{
   System.out.println("before f.get() "+new Date());
   f.get();
}

そして、これらの PacketProcessor クラスの run メソッド内で、ThreadPoolExecutor を宣言し、1 ~ 5000 の数のスレッドを作成して送信します (通常は 6 ~ 7 個のスレッドを作成します)。PacketProcessor の threadPoolExecutor コードは次のようになります。

ThreadPoolExecutor commonThreadPool =
        new ThreadPoolExecutor(
                        20,
                        20,
                        Long.MAX_VALUE,
                        TimeUnit.DAYS,
                        new LinkedBlockingQueue<Runnable>(),
                        new MyThreadFactory("commonThreadPool"));

そして最後に、これを約20分間実行し、VisualVM、メモリ使用量、およびライブスレッド数が常に上昇していることを確認しました。何が問題ですか ?

注 : 詳細情報や質問については、遠慮なくお尋ねください。

ここにいくつかの情報を含むスクリーンショットがあります:

ここに画像の説明を入力

編集1:

270 MB のヒープ ダンプを取得しました。160MB の char[] が見つかりました。そして、1000〜2000千のクエリ文字列を見つけました。StringBuilder を使用してクエリ文字列を作成します。なぜGCされないのですか?

4

3 に答える 3

2

Executor は、アプリケーションの起動時に一度宣言され、再利用されることを意図しています。それ以外の場合は、個々のスレッドをオンデマンドで作成することもできます。アプリケーションの実行中に新しいエグゼキューターを作成し続けると、それらのスレッドは実行されたままになるため、スレッド数は増加し続けます。

したがって、DI フレームワークを使用してエグゼキュータを作成し、それらをコードに挿入するだけです。または、小規模なプロジェクトの場合は、静的フィールドに配置します。

于 2012-09-18T08:17:01.210 に答える
1

runメソッドで、ThreadExecutorPoolを宣言します

2秒ごとに実行されるrunメソッドでThreadExecutorPoolを宣言すると、数分で多くのスレッドを取得できます。

于 2012-09-18T08:20:21.770 に答える
0

ExecutorService問題は、スレッドを作成し、それらを永久に存続させるために作成するすべてのsに指示したことです。これは、コードで非常に明白です。

new ThreadPoolExecutor(
                        20,
                        20,
                        Long.MAX_VALUE,
                        TimeUnit.DAYS,
                        new LinkedBlockingQueue<Runnable>(),
                        new MyThreadFactory("commonThreadPool"));

3番目と4番目の引数は、基本的に「アイドル状態のスレッドを(実質的に)無限の日の間存続させる」と述べています。

これはいくつかの方法で解決できます。

  1. ExecutorService.shutdownタスクの受け渡しが完了したら、エグゼキュータインスタンスを呼び出します。
  2. 最善の解決策は、単一ScheduledExecutorServiceのより合理的なタスク分散ロジックを使用して、スレッドの数を制限し、スレッドコンテキストの切り替えを防ぐことでパフォーマンスを向上させることです。
于 2012-09-18T08:30:27.120 に答える