2014-12-04 171 views
4

我有一個多線程控制檯應用程序,它從兩個不同的來源獲取輸入。一個是用戶輸入控制檯,另一個是網絡。我使用BufferedReader.readline()從用戶那裏獲得輸入,並且阻止,這很好,除非我在等待時接收網絡輸入。在這種情況下,我需要通過取消readline()來取消阻止用戶線程。在Java中可以在關閉它後重新打開System.in

我想取消的最好方法是關閉System.in並使readline()拋出異常。之後,雖然我需要重新打開它。那可能嗎?

+0

我認爲這是一個沒有。 – Secondo 2014-12-04 05:18:22

+0

可以爭辯說[你不應該關閉'System.in',因爲你沒打開它](http://stackoverflow.com/a/7457737/545127)。 – Raedwald 2015-06-22 11:58:07

回答

7

無法重新打開System.in,System.outSystem.err。底層本地流是連接到其他進程的文件描述符,或連接到應用程序無法識別的文件。一旦基礎本地文件描述符關閉,就不可能重新打開它們。

我可以建議的最好的方法是爲System.in對象創建一個包裝InputStream類,並將包裝器編碼爲將close()視爲無操作。或者,也可以將包裝器設置爲「關閉」狀態,而不實際關閉包裝流。

在您的具體使用情況,這是行不通的,因爲你「需要」疏通而從System.in讀取被阻塞線程。所以在你的情況下,你需要做System.in的非阻塞輸入。例如,使用available()方法來測試是否有任何要從控制檯讀取的字符。 (假設如果available()返回一個大於零的數字,您將能夠讀取整行)通常是安全的。)

(它也可以使用Selector實現非阻塞讀取,但我不能「噸認爲這是能夠得到的System.in對象‘可選擇信道’。)


注意Thread.interrupt()將不起作用。根據javadocs的說法,它只有在你從可中斷的頻道讀取時纔有效。

  • System.in是不是一箇中斷的通道上,並

  • 如果是,那麼interrupt()的記錄的行爲是信道獲取由中斷關閉。

+0

但user1379635想要使用close()來中斷該線程。使它成爲無操作不會實現這一點,所以不需要調用close():)將包裝器設置爲「關閉」狀態不會中斷塊線程。 – slipperyseal 2014-12-04 05:40:23

+0

感謝您的回答。看起來我不得不做一些重新設計。 – ForeverNoobie 2014-12-04 11:58:23

1

我有同樣的問題,我覺得很奇怪,至少可以說這個問題沒有被java本身所支持:我們是不是錯過了什麼?

無論如何,感謝斯蒂芬C,這裏是使用他的想法與匿名類一個小例子(內聯,創建了system.in掃描儀時)

(我用FilterInputStream的代替InputStream的,所以我可以通過System.in的構造函數)

希望這是一些使用給您

public class MultiopenScanner { 
    public static int scanInt() throws IOException{ 
     //Scanner sc = new Scanner(System.in); 
     Scanner sc = new Scanner(new FilterInputStream(System.in){public void close(){}}); 
     int res = sc.nextInt(); 
     sc.close(); 
     return res; 
    } 

    public static void main(String[] args) throws IOException { 
     int i=1; 
     while (i>0) { 
      System.out.println("Give me an int please : "); 
      //some might need this : System.out.flush(); 
      i = scanInt(); 
      System.out.println("got "+i); 
     } 
     System.out.println("done"); 
    } 
} 
相關問題