簡體   English   中英

中斷BufferedReader#readLine()而不關閉InputStream

[英]Interrupt BufferedReader#readLine() without closing InputStream

每當用戶想要查看它時,我的ProcessInputStream都應該附加和分離。 附着工作正常,但分離失敗。 中斷readLine()方法的默認答案總是關閉流,但在這種情況下我不能或者Process將完成或至少不能用於將來的附件。 這是流的讀取方式:

BufferedReader reader = new BufferedReader(new InputStreamReader(getProcess().getInputStream()));
String line;

while ((line = reader.readLine()) != null) {
    System.out.println(line);
}

為了分離,我嘗試了一些東西:

  • 關閉任何流,失敗:close方法阻塞並等待readLine()
  • 使用SequenceInputStream實現另一個流來發送null / abortion值,失敗:當一個InputStream正在等待輸入時,另一個甚至沒有被調用
  • 使用反射解鎖任何流內的read()方法,失敗:不確定原因,但不起作用。 我們應該繼續這個嘗試嗎? 這是源代碼:

     try { Field modifiers = Field.class.getDeclaredField("modifiers"); modifiers.setAccessible(true); Field fdecoder = stream.getClass().getDeclaredField("sd"); fdecoder.setAccessible(true); modifiers.setInt(fdecoder, 1); StreamDecoder decoder = (StreamDecoder) fdecoder.get(stream); Field flock = decoder.getClass().getSuperclass().getDeclaredField("lock"); flock.setAccessible(true); modifiers.setInt(flock, 1); Object lock = (Object) flock.get(decoder); synchronized (lock) { lock.notifyAll(); } } catch (NoSuchFieldException | IllegalAccessException e) { Wrapper.handleException(Thread.currentThread(), e); } 

不知道如何解決這個問題。 你能幫我打斷readLine()方法而不關閉流,簡單而高效嗎? 謝謝。

編輯: “高性能”是什么意思? 我的應用程序用戶不多,但有很多進程。 @EJP的答案並沒有錯 - 但在我的應用程序中無法滿足要求。 我無法為數百個進程提供數百個線程,但我可以擁有與用戶觀看的一樣多的進程。 這就是為什么我試圖優雅地中斷這個過程。 線程更少,線程運行/阻塞更少。 以下是描述的應用程序( https://imgur.com/VUcYUfi.png )向用戶發送信息的線程與讀取輸入的線程相同。

我沒想到它會起作用,但期貨實際上是可以取消的(但為什么?)。 在@Tarun Lalwani提到Googles Guava庫的TimeLimiter之后,我檢查了代碼,在我的例子中嘗試過(工作!)並重寫了一下 - 讓它不是基於時間的,而是基於方法調用的?!

以下是我從研究中得到的: BufferedReader的包裝器:

public class CancelableReader extends BufferedReader {

    private final ExecutorService executor;
    private Future future;

    public CancelableReader(Reader in) {
        super(in);
        executor = Executors.newSingleThreadExecutor();
    }

    @Override
    public String readLine() {

        future = executor.submit(super::readLine);

        try {
            return (String) future.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } catch (CancellationException e) {
            return null;
        }

        return null;

    }

    public void cancelRead() {
        future.cancel(true);
    }

}

這個class允許你在需要時使用BufferedReader#readLine() ,當你想繼續/中斷它正在運行的Thread時取消它。這里有一些示例代碼:

public static void main(String[] args) {

    System.out.println("START");

    CancelableReader reader = new CancelableReader(new InputStreamReader(System.in));
    String line;

    new Thread(() -> {

        try {

            Thread.sleep(10000);
            reader.cancelRead();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }).start();

    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }

    System.out.println("END");

}

它的輸出:

START
> Hello World!
Hello World!
> What's up?
What's up?
END //Exactly after 5 seconds, when the cancel was called
> Hey, you still there?
//No output as expected

我想說的最后一件事就是為什么這個並沒有關閉InputStream或者每個進程創建一個Thread? 在這種情況下, InputStreamProcess的流,這意味着我們無法關閉它。 一種方法是取消阻塞readLine()並返回null來完成while -loop,但這是使用Reflection ,它現在不像我們的解決方案那么漂亮,並且因任何原因都無法工作。 該應用程序使用許多進程,但用戶數量有限 - 這就是為什么我們決定每個用戶而不是每個進程的線程數量。

我希望你們將來會找到這個主題,它對你有所幫助。 如果你留下一個upvote會很棒,所以我可以取回我的獎金代表。 不要忘記贊成評論! 他們幫了我很多,並把我帶到了正確的解決方案: 中斷BufferedReader#readLine()而不關閉InputStream

你要回到前面。

您無法停止收集進程的輸出,或者您將停止子進程。

您希望在用戶不想看到它時停止顯示輸出。 僅將其視為用戶界面問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM