我有一個多線程控制檯應用程序,它從兩個不同的來源獲取輸入。一個是用戶輸入控制檯,另一個是網絡。我使用BufferedReader.readline()從用戶那裏獲得輸入,並且阻止,這很好,除非我在等待時接收網絡輸入。在這種情況下,我需要通過取消readline()來取消阻止用戶線程。在Java中可以在關閉它後重新打開System.in
我想取消的最好方法是關閉System.in並使readline()拋出異常。之後,雖然我需要重新打開它。那可能嗎?
我有一個多線程控制檯應用程序,它從兩個不同的來源獲取輸入。一個是用戶輸入控制檯,另一個是網絡。我使用BufferedReader.readline()從用戶那裏獲得輸入,並且阻止,這很好,除非我在等待時接收網絡輸入。在這種情況下,我需要通過取消readline()來取消阻止用戶線程。在Java中可以在關閉它後重新打開System.in
我想取消的最好方法是關閉System.in並使readline()拋出異常。之後,雖然我需要重新打開它。那可能嗎?
無法重新打開System.in
,System.out
或System.err
。底層本地流是連接到其他進程的文件描述符,或連接到應用程序無法識別的文件。一旦基礎本地文件描述符關閉,就不可能重新打開它們。
我可以建議的最好的方法是爲System.in
對象創建一個包裝InputStream
類,並將包裝器編碼爲將close()
視爲無操作。或者,也可以將包裝器設置爲「關閉」狀態,而不實際關閉包裝流。
在您的具體使用情況,這是行不通的,因爲你「需要」疏通而從System.in
讀取被阻塞線程。所以在你的情況下,你需要做System.in
的非阻塞輸入。例如,使用available()
方法來測試是否有任何要從控制檯讀取的字符。 (假設如果available()
返回一個大於零的數字,您將能夠讀取整行)通常是安全的。)
(它也可以使用Selector
實現非阻塞讀取,但我不能「噸認爲這是能夠得到的System.in
對象‘可選擇信道’。)
注意Thread.interrupt()
將不起作用。根據javadocs的說法,它只有在你從可中斷的頻道讀取時纔有效。
System.in是不是一箇中斷的通道上,並
如果是,那麼interrupt()
的記錄的行爲是信道獲取由中斷關閉。
但user1379635想要使用close()來中斷該線程。使它成爲無操作不會實現這一點,所以不需要調用close():)將包裝器設置爲「關閉」狀態不會中斷塊線程。 – slipperyseal 2014-12-04 05:40:23
感謝您的回答。看起來我不得不做一些重新設計。 – ForeverNoobie 2014-12-04 11:58:23
我有同樣的問題,我覺得很奇怪,至少可以說這個問題沒有被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");
}
}
我認爲這是一個沒有。 – Secondo 2014-12-04 05:18:22
可以爭辯說[你不應該關閉'System.in',因爲你沒打開它](http://stackoverflow.com/a/7457737/545127)。 – Raedwald 2015-06-22 11:58:07