![](/img/trans.png)
[英]BufferedReader#readLine() hangs even though a line has been read
[英]Interrupt BufferedReader#readLine() without closing InputStream
每當用戶想要查看它時,我的Process
的InputStream
都應該附加和分離。 附着工作正常,但分離失敗。 中斷readLine()
方法的默認答案總是關閉流,但在這種情況下我不能或者Process
將完成或至少不能用於將來的附件。 這是流的讀取方式:
BufferedReader reader = new BufferedReader(new InputStreamReader(getProcess().getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
為了分離,我嘗試了一些東西:
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? 在這種情況下, InputStream
是Process
的流,這意味着我們無法關閉它。 一種方法是取消阻塞readLine()
並返回null來完成while
-loop,但這是使用Reflection
,它現在不像我們的解決方案那么漂亮,並且因任何原因都無法工作。 該應用程序使用許多進程,但用戶數量有限 - 這就是為什么我們決定每個用戶而不是每個進程的線程數量。
我希望你們將來會找到這個主題,它對你有所幫助。 如果你留下一個upvote會很棒,所以我可以取回我的獎金代表。 不要忘記贊成評論! 他們幫了我很多,並把我帶到了正確的解決方案: 中斷BufferedReader#readLine()而不關閉InputStream
你要回到前面。
您無法停止收集進程的輸出,或者您將停止子進程。
您希望在用戶不想看到它時停止顯示輸出。 僅將其視為用戶界面問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.