2013-12-09 66 views
3

我有兩個線程在運行,userInputThread等待用戶從命令行輸入,interrupterThread在啓動後1秒鐘嘗試中斷userInputThread。顯然,您不能中斷System.in阻止的線程。另一個答案建議在中斷線程之前用System.in.close()關閉System.in。但是,當我運行以下代碼時,userInputThread永遠不會中斷,應用程序只是掛起而不關閉。中斷等待用戶輸入的線程,然後退出應用程序

class InputInterruptionExample { 

    private Thread userInputThread; 
    private Thread interrupterThread; 

    InputInterruptionExample() { 
     this.userInputThread = new Thread(new UserInputThread()); 
     this.interrupterThread = new Thread(new InterrupterThread()); 
    } 

    void startThreads() { 
     this.userInputThread.start(); 
     this.interrupterThread.start(); 
    } 
    private class UserInputThread implements Runnable { 
     public void run() { 
      try { 
       System.out.println("enter your name: "); 
       String userInput = (new BufferedReader(new InputStreamReader(System.in))).readLine(); 
      } catch (IOException e) { 
       System.out.println("Oops..somethign went wrong."); 
       System.exit(1); 
      } 
     } 
    } 
    private class InterrupterThread implements Runnable { 
     public void run() { 
      try { 
       sleep(1000); 
       System.out.println("about to interrupt UserInputThread"); 
       System.in.close(); 
       userInputThread.interrupt(); 
       userInputThread.join(); 
       System.out.println("Successfully interrupted"); 
      } catch (InterruptedException e) { 
      } catch (IOException ex) { 
       System.out.println("Oops..somethign went wrong."); 
       System.exit(1); 
      } 
     } 
    } 
    public static void main(String[] args) { 
     InputInterruptionExample exampleApp = new InputInterruptionExample(); 
     exampleApp.startThreads(); 
    } 
} 

不過已經有了類似的question,但目前還沒有任何明確的答案。

回答

3

這已經解決了這個問題:

class InputInterruptionExample { 

    private UserInputThread userInputRunnable; 
    private Thread userInputThread; 
    private Thread interrupterThread; 

    InputInterruptionExample() { 
     this.userInputRunnable = new UserInputThread(); 
     this.userInputThread = new Thread(userInputRunnable); 
     this.interrupterThread = new Thread(new InterrupterThread()); 
    } 

    void startThreads() { 
     this.userInputThread.start(); 
     this.interrupterThread.start(); 
    } 
    private class UserInputThread implements Runnable { 
     private InputStreamReader isr; 
     private BufferedReader br; 

     UserInputThread() { 
      InputStreamReader isr = new InputStreamReader(System.in); 
      BufferedReader br = new BufferedReader(isr); 
     } 

     public void run() { 
      try { 
       System.out.println("enter your name: "); 
       try{ 
        String userInput = br.readLine(); 
       } catch(NullPointerException e) {} 
      } catch (IOException e) { 
       System.out.println("Oops..somethign went wrong."); 
       System.exit(1); 
      } 
     } 
     public void closeBufferdReader() { 
      try { 
       System.in.close(); 
      } catch (IOException e) { 
       System.out.println("Oops..somethign went wrong in closeBufferdReader() method"); 
       System.exit(1); 
      } 
     } 
    } 
    private class InterrupterThread implements Runnable { 
     public void run() { 
      try { 
       sleep(1000); 
       userInputRunnable.closeBufferdReader();     
       userInputThread.interrupt(); 
       userInputThread.join(); 
       System.out.println("Successfully interrupted"); 
      } catch (InterruptedException e) {} 
     } 
    } 
    public static void main(String[] args) { 
     InputInterruptionExample exampleApp = new InputInterruptionExample(); 
     exampleApp.startThreads(); 
    } 
} 

更新:時的BufferedReader是這樣拆分這僅適用於:

InputStreamReader isr = new InputStreamReader(System.in); 
BufferedReader br = new BufferedReader(isr); 
String userInput = br.readLine(); 

出於某種原因中斷似乎沒有當readLine()結構被寫爲一個字符串時工作:

this.userInput = (new BufferedReader(new InputStreamReader(System.in))).readLine(); 

因此,雖然可以中斷分裂的BufferedReader結構中的線程,但現在無法讀取用戶的輸入。

如果有人能夠展示一種方式來獲得用戶輸入,並且在用戶沒有及時提供任何輸入(中斷器正在休眠)時中斷UserInputThread,請執行。

+0

非常酷。通過關閉流強制NPE。先生+1。 – claymore1977

+1

我認爲它也適用於closeBufferdReader – user1121883

+0

@ user1121883你是對的。出於某種原因,我認爲你不能中斷()System.in阻塞的線程。嗯... – Sbbs

0

我的所有研究都讓我相信.readLine()調用中的底層.read()不能被中斷(至少不會破壞System.in所附帶的進程)。此時唯一的其他選擇是使用輪詢IO方案或切換到NIO。

下面是你的代碼到輪詢IO方案中的一個快速(和非常髒/醜)適應。這不是一箇中介解決方案,所以它不是直接回答你的問題,而是希望讓你獲得你想要的行爲。

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.concurrent.atomic.AtomicBoolean; 

public class InputInterruptionExample { 

    private UserInputThread uiThreadObj = null; 
    private Thread inputThread = null; 
    private Thread interrupThread = null; 

    public InputInterruptionExample() { 
     this.uiThreadObj = new UserInputThread(); 
     this.inputThread = new Thread(this.uiThreadObj); 
     this.interrupThread = new Thread(new InterrupterThread()); 
    } 

    void startThreads() { 
     this.inputThread.start(); 
     this.interrupThread.start(); 
    } 

    private class UserInputThread implements Runnable { 
     private final AtomicBoolean runCmd = new AtomicBoolean(true); 

     public void run() { 
      try { 
       final BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 

       System.out.println("enter your name: "); 
       while (this.runCmd.get()) { 
        if (System.in.available() > 0) { 
         String userInput = br.readLine(); 
         System.out.println("You typed: " + userInput); 
         System.out.println("enter your name: "); 
        } else { 
         Thread.sleep(5); //minimal sleep to prevent CPU peg 
        } 
       } 
       System.out.println("Finishing normally."); 

      } catch (IOException e) { 
       System.out.println("Oops..somethign went wrong."); 
       System.exit(1); 
      } catch (Exception e) { 
       System.out.println("What'd you do?!"); 
       e.printStackTrace(); 
      } 
     } 

     public final void requestStop() { 
      this.runCmd.set(false); 
     } 
    } 
    private class InterrupterThread implements Runnable { 
     public void run() { 
      try { 
       Thread.sleep(1000 * 10); 
       System.out.println("Requesting that UserInputThread stop."); 
       uiThreadObj.requestStop(); 
       System.out.println("Request made."); 
      } catch (InterruptedException e) { 
       System.out.println("Oops..somethign went wrong."); 
       System.exit(1); 
      } 
     } 
    } 
    public static void main(String[] args) { 
     InputInterruptionExample exampleApp = new InputInterruptionExample(); 
     exampleApp.startThreads(); 
    } 
} 
+0

我跑你的例子,它也掛起。 'interrupThread'應該停止'inputThread',應用程序應該退出。感謝您的嘗試,但您的回答並未解決問題。 – Sbbs

+0

有趣。 「適用於我」適用於此,但我真的很想知道爲什麼它會掛在你的機器上。它掛在哪條線上? – claymore1977

+0

它掛在'輸入你的名字:'行。 – Sbbs

相關問題