8

Java.NIO ソケット サーバーにスレッド プールがあります。Connection reset by peerBroken Pipeなどの実行時エラーが発生することがありました。

私の質問は: 例外がスローされたときにスレッドが強制終了されていますか? もしそうなら - スレッドプールで、殺されたスレッドの代わりに新しいスレッドが作成されていますか??

これは私の ThreadManager です:

import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class ThreadsManager {

    private ExecutorService threadPool = null;
    private LiveConnectionsManager liveConnectionsManager;
    private int threadPoolSize = 35; //number of tasks thread

    public ThreadsManager(LiveConnectionsManager liveConnectionsManager) {
        this.liveConnectionsManager = liveConnectionsManager;
        threadPool = Executors.newFixedThreadPool(threadPoolSize);
        ServerActions.threadPool = threadPool;
    }

    public void processNewMessage(SocketChannel socketChannel, Client client)
    {
        threadPool.execute(new MessagesProcessor(socketChannel, client, liveConnectionsManager));
    }

    public void closeConnection(SocketChannel socketChannel, Client client) {
        threadPool.execute(new LogoutClient(socketChannel, client, null));
    }   
}
4

3 に答える 3

12

ExecutorServiceを使用してスレッド プールを作成します。

はい、ExecutorService.newFixedThreadPool (..)は、スレッドが例外/エラーによって強制終了され、スレッドを待機している十分なタスクがある場合、スレッドの数が一定であることを保証します。以下の Java doc のテキストには、明確に記載されています。

Java doc から直接:newFixedThreadPool

無制限の共有キューで動作する固定数のスレッドを再利用するスレッド プールを作成します。どの時点でも、最大で nThreads スレッドがアクティブな処理タスクになります。すべてのスレッドがアクティブなときに追加のタスクが送信されると、それらのタスクは、スレッドが使用可能になるまでキューで待機します。シャットダウン前の実行中に障害が発生していずれかのスレッドが終了した場合、必要に応じて後続のタスクを実行するために新しいスレッドが代わりに使用されます。プール内のスレッドは、明示的にシャットダウンされるまで存在します。

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int )

于 2013-01-19T14:05:17.670 に答える
4

ThreadPoolExecutor、選択した設定に基づいてスレッドの数を管理します (コンストラクターに渡されるか、使用したヘルパー メソッドを介して)。ThreadPoolExecutor javadoc で説明されているように機能します。

コンストラクター (以下にリスト) からの最も興味深いパラメーターはcorePoolSizemaximumPoolSizeです。corePoolSize存続するスレッドの最小量です。スレッドが強制終了され、これによりスレッドの数がこの数を下回ると、新しいスレッドが開始されます[1] (ある時点で)。

maximumPoolSizeプール内のスレッドの最大数です。これが より大きい場合corePoolSize、プールは、パラメータで指定したよりも多くのスレッドになる可能性がありcorePoolSizeます。この時点でスレッドの 1 つが停止し、ライブ スレッドの数が数を下回らないcorePoolSize場合、新しいスレッドは作成されません。

Executorsヘルパー クラスを介して作成している固定スレッド プールには corePoolSize == maximumPoolSize があるため、実際には、サービスは同じ量のスレッドが常に利用可能であることを確認します[1] (必要な場合)。

[1]重要な注意点として、スレッドの作成は「オンデマンド」で行われるということです。つまり、スレッドが終了し、キューにタスクがない場合、スレッドは必要がなくなるまで作成されません (上記のエンキューによって)。すでに利用可能なスレッド)。

/**
 * Creates a new <tt>ThreadPoolExecutor</tt>( ... cut irelevant part ... )
 *
 * @param corePoolSize the number of threads to keep in the
 * pool, even if they are idle.
 * @param maximumPoolSize the maximum number of threads to allow in the
 * pool.
 * ( ... cut irelevant part ... )
 */
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

[編集] - 他の質問を忘れました。実際、例外はワーカー スレッドを強制終了します。内部でエラーを処理する必要があります。詳細については、java.util.concurrent.ThreadPoolExecutor.Worker クラスを確認してください。その runTask メソッドはチェックする価値があります。

于 2013-01-19T14:13:06.747 に答える
0

私の質問は、エラーがキャッチされたときにスレッドが強制終了されるかどうかです。

もしそうなら-スレッドプールはプール内のその位置を新しいスレッドで埋めますか?

によって作成されたエグゼキュータExecutors.newFixedThreadPoolは、プール内のスレッドの1つが停止した場合に新しいスレッドを作成するため、質問の2番目の部分に対する答えは「はい」です。MessagesProcessor最初の部分については、とのコードを見ずに言うことは不可能ですがLogoutClient、デッドスレッドが置き換えられることを考えると、どちらの方法でも実際には問題ではありません。MessagesProcessor例外を内部でLogoutClientキャッチしてログに記録する場合

public void run() {
  try {
    // do stuff
  } catch(Exception e) {
    e.printStackTrace();
  }
}

その場合、例外はメソッドから伝播されrunないため、タスクを実行しているスレッドを強制終了しないため、プールに戻ることができます。ただし、例外をキャッチせずRuntimeException、メソッドからaをスローできるようにするrunと、スレッドは停止します(新しいスレッドに置き換えられます)。

于 2013-01-19T14:10:18.610 に答える