2012-04-05 22 views
1

私は現在、複数のクライアントが接続するサーバーを作成しています。通信プロトコルは、基本的にサーバーがクライアントにタスクを送信し、クライアントがタスクの実行時に応答することです。クライアントはサーバーに接続したままで、切断しないでください。新しいスレッドの代わりにサーバーソケットクライアント用のExecutorを使用

現在、私は各クライアントを扱う新しいスレッドを開始しています。 (Java Concurrency in practiceからソース)

public class ThreadPerTaskWebServer { 
    public static void main(String[] args) throws IOException { 
     ServerSocket socket = new ServerSocket(80); 
     while (true) { 
      final Socket connection = socket.accept(); 
      Runnable task = new Runnable() { 
       public void run() { 
        handleRequest(connection); 
       } 
      }; 
      new Thread(task).start(); 
     } 
    } 

    private static void handleRequest(Socket connection) { 
     // request-handling logic here 
    } 
} 

しかし、彼らはより安定したように見えるし、より良いスケールので、私はエグゼキューを使用したい:精神で私の現在のソリューションは、このようなものです。したがって、サーバーがクライアントにメッセージを送信できるようにするには、クライアントを実行するExecutorとは別にクライアントを追跡する必要があります。だから私はどこCopyOnWriteArrayListとクライアントでクライアントを配置し、サーバ・クラスでこのような何かを持っている場合:また、これは、すべてのクライアントにコマンドを送信するために、私はCopyOnWriteArrayListとを反復することが可能になる

Socket clientSocket = serverSocket.accept(); 
// The runnable that takes care of a client 
ClientHandler c = new ClientHandler(clientSocket, this); 
// Start executing the ClientHandler 
exec.execute(c); 
// Add clients to CopyOnWriteArrayList 
clients.add(c); 

と切断されたものを削除します。これは堅牢なソリューションでしょうか?何らかの理由で実行可能ファイルが例外を伝播する場合、Executorで何が起こるでしょうか?

+0

クライアントとサーバーが混在しています。あなたのケースでは、クライアントはサーバーであり、逆もまた同様です。 – ahanin

+1

@ahanin私はそれが完全にはっきりしていないことに同意するが、これは* most *正しい記述だと思う。クライアントはサーバに接続しているので(ServerSocketを持っています)、それはサーバの定義になります:) – Teletha

+0

私は混乱していません。私は意図が何であるかを完全に理解しています。@Telethaがコンセプトを混ぜていることを指摘したい。上記のケースでは、クライアントは、タスク実行のための「サーバ」要求を提供する種類のワーカーエージェントである。 – ahanin

答えて

1

これは堅牢なソリューションでしょうか?

はい、そうです。固定サイズのプールに適切な数のスレッドを割り当てるか、動的プールを使用するかを確認する必要があります。

何らかの理由で実行可能ファイルが例外を伝播すると、実行者はどうなりますか?

コードがRuntimeExceptionをスローした場合、コードを実行するエグゼキュータ・プールのスレッドは停止しますが、サービスが既にシャットダウンされていない場合、プールのスレッド数がデクリメントされ、別のスレッドが作成しました。そのため、スレッドプールは適切に動作し続けます。

これは、あなたが参照を保存していない限りあなたが切断さのものを削除する必要はありません、私はすべてのクライアントにコマンドを送信するためにはCopyOnWriteArrayListとを反復しても切断さのもの

を削除することができますもちろんそれらに。それ以外の場合、私は本当にこの要件にコメントすることはできません。

1

接続あたりのスレッド数を選択し、NIO APIを使用したくない場合は、これが良い解決策だと思います。ただし、プールのサイズが同時リクエストの数よりも小さい場合は、前のリクエストが終了するまでクライアントが保留中になっていることに注意してください。

タスクで例外が発生した場合、スレッドは終了しますが、エグゼキュータは他のスレッドを作成します。

関連する問題