2012-04-30 151 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'方法末尾看看線程是否退出? – Tudor

+0

當然 - 調試EchoThread並找出客戶端關閉連接時會發生什麼。 'catch(IOException異常)'是否發生?如果是這樣,你在那裏做什麼?是否應該返回以便finally可以執行,關閉套接字並退出線程? –

+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

與你的解決方案,它會工作,但如果用戶只是把頁面放在上面,一小時後,或兩個小時後,他們突然想發送一些東西,這意味着將不會寫入日誌,因爲線程已關閉。無論如何要防止這種情況?除了將超時更改爲一小時或更長時間。如果甚至可能的話,最好的解決方案是檢測用戶是否離開小程序,例如註銷,刷新或轉到其他頁面,並僅在該事件期間關閉該線程。任何例子?謝謝 – Harts

+0

你應該尋找一個'onClose()'方法或類似的東西,但我不知道Java Applets是否有這樣的方法! – StepTNT