只要用户想要查看,InputStream
的{{1}}就应该附加和分离。附着工作正常,但分离失败。中断Process
方法的默认答案始终是关闭流,但在这种情况下我无法完成或readLine()
将完成或至少不可用于将来的附件。这是流的读取方式:
Process
要分离我尝试了一些东西:
BufferedReader reader = new BufferedReader(new InputStreamReader(getProcess().getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
实现另一个流来发送null / abortion值,失败:当一个SequenceInputStream
等待输入时,另一个甚至没有被调用使用反射来解锁任何流中的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);
}
方法而不关闭流,简单而高效吗?感谢。
修改 我是什么意思"表演"?我的应用程序用户不多,但有很多进程。 @EJP的答案并没有错 - 但在我的应用程序中无法满足要求。我无法为数百个进程提供数百个线程,但我可以拥有与用户观看的一样多的进程。这就是为什么我试图优雅地打断这个过程的原因。线程更少,线程运行/阻塞更少。 这是描述的应用程序(https://imgur.com/VUcYUfi.png) 将信息发送给用户的线程与读取输入的线程相同。
答案 0 :(得分:5)
我没想到它会起作用,但期货实际上是可以取消的(但为什么呢?)。 在@Tarun Lalwani提到谷歌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
- 循环,但这是使用Reflection
进行的,这不像我们现在的解决方案那么漂亮而且没有因任何原因而工作。该应用程序使用许多进程,但用户数量有限 - 这就是为什么我们决定每个用户而不是每个进程的线程数量。
我希望你们将来会找到这个主题并且它对你有所帮助。如果你留下一个upvote会很棒,所以我可以取回我的奖金代表。 不要忘记赞成评论!他们帮了我很多,并把我带到了正确的解决方案: Interrupt BufferedReader#readLine() without closing InputStream
答案 1 :(得分:4)
你要回到前面。
您无法停止收集流程的输出,或者您将停止子流程。
当用户不想看到输出时,您希望停止显示输出。仅将其视为用户界面问题。