2011-02-13 17 views
5

我正在使用多線程環境,其中一個線程通過反覆調用scanner.nextLine()不斷偵聽用戶輸入。 要結束應用程序,此runloop被另一個線程阻止,但是偵聽線程不會停止,直到最後一個用戶輸入爲止(由於nextLine()的阻塞性質)。如何中斷java.util.Scanner nextLine調用

關閉流似乎不是一個選項,因爲我從System.in讀取,它返回一個不可關閉的InputStream

有沒有辦法中斷掃描儀的阻塞,以便它會返回?

感謝

+0

你可以調用`scanner.hasNext()`而不是`scanner.nextLine()`這個方法**可能會根據javadoc阻塞,所以你可能需要處理它。 這個想法是,不像`scanner.nextLine()`,`scanner.hasNext()`不提前輸入,所以你可以檢查一個標誌,如果讀取線程已經被另一個線程停止,然後調用`scanner.nextLine )` – 2011-02-13 08:01:43

+1

是的,但這將涉及不斷的投票。 – 2011-02-13 08:48:53

+0

您應該能夠在偵聽線程上調用Thread.interrupt,這會導致您可以從ioException()方法獲得InterruptedIOException。不確定它是如何與nextLine()交互的,或者它是否與你的基礎輸入流一起工​​作,但在大多數情況下它應該終止nextLine。 – josefx 2011-05-01 13:47:02

回答

8

article描述了一種方法來避免讀出時阻斷。它給出了代碼片斷,你可以在我的評論中指出這些代碼片段。

import java.io.*; 
import java.util.concurrent.Callable; 

public class ConsoleInputReadTask implements Callable<String> { 
    public String call() throws IOException { 
    BufferedReader br = new BufferedReader(
     new InputStreamReader(System.in)); 
    System.out.println("ConsoleInputReadTask run() called."); 
    String input; 
    do { 
     System.out.println("Please type something: "); 
     try { 
     // wait until we have data to complete a readLine() 
     while (!br.ready() /* ADD SHUTDOWN CHECK HERE */) { 
      Thread.sleep(200); 
     } 
     input = br.readLine(); 
     } catch (InterruptedException e) { 
     System.out.println("ConsoleInputReadTask() cancelled"); 
     return null; 
     } 
    } while ("".equals(input)); 
    System.out.println("Thank You for providing input!"); 
    return input; 
    } 
} 

你可以直接使用此代碼,或者寫一個新的可封閉的InputStream類,結束了這篇文章中描述的邏輯。

0

當然。使用核武器。在主線程結束時調用System.exit(0)。這將殺死一切。即使是在System.in中等待的活動線程。

問題是System.in是一個阻塞的傳統輸入流,當它阻塞線程被標記爲運行時。你不能打斷它。所以無論你使用什麼線程讀取System.in都在調用read,讀取將會阻塞該線程。你可以用一堆技巧來哄騙這些東西,避免調用閱讀,除非在這種情況下,我們可以確定沒有障礙,然後不斷進行調查。但是,沒有真正解決這個問題的方法,即任何嘗試讀取這些信息都會鎖定線程,並且無法關閉基礎數據流或者中斷或停止線程將節省您的時間。但是,如果你謀殺了整個虛擬機......線程將會死亡。

顯然你需要確保其餘的線程已經正確退出,這只是一個愚蠢的我想能夠響應輸入線程的最後一個掛鉤。但是,如果情況完全如此,那麼正確的答案是退出,或者至少是基本上唯一的解決方案,不需要無故燃燒時鐘週期並讓程序終止。