0

サーバーソケット、つまりサーバー機能をカプセル化するクラスがあります。
クラスのインターフェースは次のとおりです。

class Server{  
  public void start();  
  public void stop();  
}

開始は次のとおりです。

public void start(){  
   ExecutorService tp = Executors.newSingleThreadExecutor();  
   while(!stop){  
    try {  
        Socket clientConnection = serverSocket.accept();  
        tp.execute(new ClientProcessor(clientConnection));                
    } catch (IOException e) {  
            stop = true;
    }  
   }    

ブロックせずにこれを開始する方法を理解するのに苦労していmainます。
つまり、バックグラウンド スレッドからサーバーを起動する必要があるため、次のことを考えました。

ExecutorService tp2 = Executors.newSingleThreadExecutor();  
 tp.submit(new Runnable(){  
     public void run(){  
    Server s = new Server();
        s.start();  
     }  
 });  
}

しかし、サーバーが起動して例外をスローしなかったことを知りたいのです。どうやってやるの?つまり、バックグラウンド サーバーが正常に起動し、残りのアクションを続行できることをスレッド
から知るにはどうすればよいでしょうか?main

4

6 に答える 6

1

サーバーを起動します。ちょっと待ってください。ローカル スタックで接続を試みます。接続が成功した場合は、勝者がいます。一時的な接続を閉じるだけです。

于 2013-03-01T15:24:33.813 に答える
0

これは非常に単純な例です(ただし、より優れた、より複雑な方法はたくさんあります)。

interface Server implements Thread{
    public void startup();
    public void shutdown();
}

class MyServer implements Server{
    private Exception serverError=null;
    ExecutorService singleThreadManager;

    public Exception getServerError(){
        return serverError;
    }

    public void run(){    
       while(!stop){  
            try {  
                 Socket clientConnection = serverSocket.accept();  
                 singleThreadManager.execute(new ClientProcessor(clientConnection));               
            } catch (IOException e) { 
                 serverError = e;
                 // stop = true;
                 shutdown(); // shutdown cleanly after exception
            }
       } 
    } 

    public void startup(){
       singleThreadManager = Executors.newSingleThreadExecutor();
        // do setup tasks and then
        start(); // thread.run() will now be called asynchronously
    }
}

public static void main (String ... args){
    MyServer s = new MyServer();
    s.startup();
    // whenever you want you can now call
    Exception x = s.getServerError();
    // to see whether the server has shutdown because of an error.
}
于 2013-03-01T14:14:06.750 に答える
0

これを行う簡単な方法は、コレクション内のすべての例外を収集し、ある時点でそれらをフォアグラウンド スレッドに返すことです。

class Server{  
    private Collection<? extends Exception> exceptions = new ArrayList<Exception>();

    public void start()
    {
      try{ /* do something*/ }
      catch(Exception e)
      {
          exceptions.add(e)
      }
    }

    public void stop();

    public Collection<Exception> getAllExceptions()
    {
        return exceptions;
    }

    public boolean checkOk()
    {
        return 0 == exceptions.size();
    }    

}

スレッド間でデータを転送する方法の詳細:

上記の私の提案と同様にサーバーを宣言した場合、サーバーを生成するために使用したコードを変更して、serverStartupOk情報を転送できます。

ExecutorService tp2 = Executors.newSingleThreadExecutor();  
final boolean[] result = new boolean[1]; //Final object so it can pass between threads
 tp.submit(new Runnable(){  
     public void run(){  
    Server s = new Server();
        s.start();  
        result[0] = s.checkOk(); // Retrieve the check from the server, store it in 
                                 // final array variable
     }  
 });

boolean serverStartupOk = result[0];
System.out.println("Server startup succesful: " + Boolean(serverStartupOk).toString());
}
于 2013-03-01T14:09:24.997 に答える
0

メイン アプリケーションにイベント ハンドラを実装できるかもしれません。メイン アプリケーションは、イベント リスナーとしてサーバー クラスに登録する必要があります。

次のリンクをご覧ください。C# のイベント処理の例と、Java の同じ例が示されています。

http://scatteredcode.wordpress.com/2011/11/24/from-c-to-Java-events/

于 2013-03-01T14:19:37.583 に答える
0

ThreadPoolExecutorで事前に焼いたものではなく、独自のものを使用してくださいExecutorsafterExecute次に、TPE によって提供されるフックをオーバーライドして、例外で必要なことを行います。

于 2013-03-01T15:05:44.753 に答える
0

ここで行間を少し読んでいますが、ソケットでの最初のリッスンが成功したかどうかを知りたいようです。待機してクライアントが失敗したかどうかを確認したい場合は、別のスレッドで実行する必要はありません。

それが正しければ、スレッドを開始してクライアント接続を処理する前に、最初の TCP サーバー ソケットのインスタンス化によって発生した例外をキャッチできます。サーバーを新しいスレッドで作成するのではなく、新しいスレッドに渡します。

于 2013-03-03T09:37:40.280 に答える