2017-05-09 6 views
0

私は古典的なサーバーマルチクライアントプログラムを持っています。サーバーはServerSocketをリッスンし、受信ソケットごとに新しいRunnableクラスを作成し、ExecuteServiceで実行します。Java try-with-recourses stuck

Runnableクラスのrunメソッドでは、try-with-resourcesブロックを開きます。tryストリームでは、inputstreamから読み取り、クライアントからFINコマンドを受け取るまで出力ストリームに書き込みます。すべて正常に動作し、クライアントは正常に切断されます。実行はfinallyブロックに達し、テストのためにいくつかのものを出力しますが、tryブロックを終了しないので、runメソッドを終了しないで、どこかで実行されます。おそらくinputstreamのreadメソッドです。

興味があればコードを投稿できます。

最終的にすべてを強制終了してrunメソッドを終了するにはどうすればよいですか?

コード:
Server.java:

public static void main(String[] args) { 
    playersReady = new ArrayList<Integer>(); 
    ServerSocket server = null; 
    try { 
     server = new ServerSocket(Consts.PORT); 
     ExecutorService service = Executors.newFixedThreadPool(characters.size()); 
     while(playersReady.size()<characters.size()){ 
      RequestHandler handler = new RequestHandler(server.accept()); 
      service.execute(handler); 
     } 
     service.shutdownNow(); 
     service.shutdown(); 
     while(!service.isTerminated()){} 

     System.out.println("finished"); 

RequestHandler.java

public final class RequestHandler implements Runnable { 

    ..... 

public void run() { 
    //DataOutputStream output = null; 
    //DataInputStream input = null; 

    try (DataOutputStream output = new DataOutputStream(socket.getOutputStream()); 
      DataInputStream input = new DataInputStream(socket.getInputStream())){ 
     // socket.setSoTimeout(500); 
     handleReady(input.readUTF().split(" "), output); 
     while (/*!shutdown && !socket.isClosed() && */socket.isConnected()) { 

      System.out.println("check before read " + character.getId()); 
      String request = input.readUTF(); 
      System.out.println("check after read " + character.getId()); 

      System.out.println("-----------------------------------" + request); 
      if (shutdown) { 
       socket.shutdownInput(); 
       socket.getOutputStream().flush(); 
       socket.shutdownOutput(); 
       break; 
      } 
      String[] requestParser = request.split(" "); 
      if (requestParser[1].equals("DMG")) { 
       // handle damage request 
       handleDamage(requestParser, output); 
      } else if (requestParser[1].equals("BND")) { 
       // handle bandage request 
       handleBandage(requestParser, output); 
      } else if (requestParser[1].equals("FIN")) { 
       // handle finish request 
       handleFin(); 
       if (!socket.isClosed()) 
        socket.shutdownInput(); 
       if (!socket.isClosed()) { 
        socket.getOutputStream().flush(); 
        socket.shutdownOutput(); 
       } 
       shutdown = true; 
       break; 
      } else { 
       break; 
      } 
     } 
    } catch (SocketTimeoutException e) { 
     System.out.println(e.getMessage()); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     shutdown = true; 
     break; 
    } catch (Throwable e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
      System.out.println("finished"); 

      if (!socket.isClosed()) 
       socket.shutdownInput(); 
      if (!socket.isClosed()) { 
       socket.getOutputStream().flush(); 
       socket.shutdownOutput(); 
       socket.close(); 
      } 
      socket.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
    System.out.println("Done run"); 
} 

....


System.out.println("finished")最終的には が印刷されていますが、実行方法の最後のSystem.out.println("Done run")はありません!!

なぜですか?
これはrunメソッドでスタックされていますが、私はreadUTF呼び出しでは思いますが、すべてのリソースを閉じました!

+1

プログラムのデバッグを試しましたか?あなたの「私はreadUTF呼び出しで考える」というのは少し曖昧です。 – f1sh

+0

私は何も特別なことはしませんでしたが、runメソッドを渡してJavaのRunnableクラスに移動して停止しますが、スレッドは実行を継続します – faris

答えて

3

あなたはその行の前に戻るので、実行されません。最終ブロックはの最終ブロックであるため、とにかく実行されます。最後にブロックが常に実行されますが、このルールの例外は1つだけです:System.exit()しかし、これは当てはまりません。

+0

どの行ですか? runメソッドは完全に実行され、停止せず、関連付けられたスレッドを停止しません。 – faris

+0

ああ、私はすべての "return"ステートメントを "break"に変更しました。これで最終的な印刷コマンドが印刷されるようになりましたが、スレッドは停止しません。サーバーのrunメソッドを続行しない – faris