2012-04-30 10 views
1

私のサーバーアプリケーションは平均CPU使用率が約95%です。理由は、新しいスレッドを生成し続けるが、閉じないという理由だと思う。このようなことが起こったときにスレッドを閉じるにはどうすればよいですか?リフレッシュページ、ログアウト、ブラウザーが閉じられました。マルチスレッド環境でスレッドを閉じるにはjava

私のコードは、サーバーの部分ではこれとほぼ同じです。

ThreadedEchoServer.java

public class ThreadedEchoServer { 
    // using port 2000 
    static final int PORT = 2000; 

    public static void main(String args[]) { 
     ServerSocket serverSocket = null; 
     Socket socket = null; 

     try { 
      serverSocket = new ServerSocket(PORT); 
     } catch (IOException e) { 
      e.printStackTrace(); 

     } 
     while (true) { 
      try { 
       socket = serverSocket.accept(); 
      } catch (IOException e) { 
       System.out.println("I/O error: " + e); 
      } 

      // new thread for a client 
      new EchoThread(socket).start(); 
     } 
    } 
} 

EchoThread.java

/* 
Class for java server to accept incoming stream 
and create a new thread to save log file data in server 
*/ 
public class EchoThread extends Thread { 
    protected Socket socket; 

    public EchoThread(Socket clientSocket) { 
     this.socket = clientSocket; 
    } 

    public void run() { 
     /*Create a File*/ 
     int i = 1; 
     try { 
      File directory = new File("F:/temp/tmplog/" + getDate()); 
      if(!directory.exists()) { 
       directory.mkdir(); 
      } 

      String fileName = "F:/temp/tmplog/" + getDate() + "/" + getDateTime() + ".txt"; 
      File file = new File(fileName); 

      //Double Make Sure it create the file 
      while(file.exists()) { 
       file = new File(fileName + "." + i); 
       i++; 
      } 
      FileOutputStream fis = new FileOutputStream(file, true); 
      PrintStream out = new PrintStream(fis); 
      System.setOut(out); 


      while (true) { 
       try { 
       InputStream is = socket.getInputStream(); 
       BufferedReader br = new BufferedReader(new InputStreamReader(is, "US-ASCII")); 

       String line = null; 

       while ((line = br.readLine()) != null) { 
        System.out.println(line); 
       } 
       } catch (IOException exception) { 
       // Just handle next request. 
       } finally { 
       if (socket != null) { 
        try { 
        socket.close(); 
        } catch (IOException ignored) { 
        } 
       } 
       fis.close(); 
       } 
      } 


     } catch (IOException ignored) { 
     } 
    } 

このサーバアプリはbasicly新しいを開いて、すべてのスレッド/クライアントのログファイルを書き込みます。私は問題は私が使用後にスレッドを閉じることではないと思う。だからこそ、新しいスレッドを生み出し続けるのです。どんな助け?

+0

は、あなたはそれがこのループを離れるかどうかを確認するために、 'println'を置くことができます:'しばらく(file.exists())... '?また、 'run'メソッドの最後に、スレッドが終了するかどうかを調べるもう1つのメソッドがありますか? – Tudor

+0

確かに - EchoThreadをデバッグして、クライアントが接続を閉じたときに何が起こるかを調べてください。 'catch(IOException exception)'は起こりますか?もしそうなら、あなたはそこで何をしていますか?最終的に実行できるように戻り値がなければならない、ソケットを閉じてスレッドを終了する? –

+0

@MartinJames私が分からない部分は、新しいストリームを待っているので、スレッドが終了するかどうかです((line = br.readLine())!= null){}。ユーザーがページをリフレッシュするか、ブラウザを閉じるとどうなりますか?自動的にそのループを終了するか、またはループを終了する方法を確認することができます。 – Harts

答えて

1

私はあなたが探しているものを理解している場合、あなただけのこの状況に対処するために、タイムアウトを使用することができます。 タイムアウトが切れると、スレッドが終了します。

EchoThread

/* 
Class for java server to accept incoming stream 
and create a new thread to save log file data in server 
*/ 
public class EchoThread extends Thread { 
    protected Socket socket; 

    public EchoThread(Socket clientSocket) { 
     this.socket = clientSocket; 
     this.socket.setSoTimeout(10000); //Sets timeout to 10 seconds 
    } 

    public void run() { 
     /*Create a File*/ 
     int i = 1; 
     try { 
      File directory = new File("F:/temp/tmplog/" + getDate()); 
      if(!directory.exists()) { 
       directory.mkdir(); 
      } 

      String fileName = "F:/temp/tmplog/" + getDate() + "/" + getDateTime() + ".txt"; 
      File file = new File(fileName); 

      //Double Make Sure it create the file 
      while(file.exists()) { 
       file = new File(fileName + "." + i); 
       i++; 
      } 
      FileOutputStream fis = new FileOutputStream(file, true); 
      PrintStream out = new PrintStream(fis); 
      System.setOut(out); 


      while (true) { 
       try { 
       InputStream is = socket.getInputStream(); 
       BufferedReader br = new BufferedReader(new InputStreamReader(is, "US-ASCII")); 

       String line = null; 

       while ((line = br.readLine()) != null) { 
        System.out.println(line); 
       } 
       } catch (IOException exception) { 
       // Just handle next request. 
       } finally { 
       if (socket != null) { 
        try { 
        socket.close(); 
        } catch (IOException ignored) { 
        } 
       } 
       fis.close(); 
       } 
      } 


     } catch (IOException ignored) { 
     } catch (SocketException e) { //Exception thrown by timeout 
      socket.close(); //We close the socket 
      this.stop(); //We stop the thread 
     } 
    } 
+0

あなたのソリューションでは、それは動作しますが、ユーザーがページを置くだけで1時間後、または2時間後に突然何かを送信したい場合、つまりログが書き込まれないことを意味しますスレッドは既に閉じられています。とにかくこれを防ぐためにそこにいますか?タイムアウトを1時間以上に変更します。もし可能であれば、ユーザーがログアウト、リフレッシュ、または他のページへの移動など、アプレットから離れて移動したかどうかを検出し、そのイベント中にのみスレッドを閉じるのが最善の解決策です。どのような例ですか?ありがとうございます – Harts

+0

'onClose()'メソッドなどを探すべきですが、Javaアプレットにそのようなメソッドがあるかどうかはわかりません! – StepTNT

関連する問題