如何中断 java.util.Scanner nextLine 调用
我正在使用多线程环境,其中一个线程通过重复调用 scanner.nextLine() 不断侦听用户输入。 要结束应用程序,此运行循环将由另一个线程停止,但侦听线程直到最后一次用户输入后才会停止(由于 nextLine()
的阻塞性质)。
关闭流似乎不是一个选项,因为我正在从 System.in
读取内容,它返回一个不可关闭的 InputStream
。
有没有办法中断扫描仪的阻塞,使其返回?
谢谢
I am using a multi threaded environment were one Thread is constantly listening for user input by repeatedly calling scanner.nextLine()
.
To end the application, this runloop is stopped by another thread, but the listening thread won't stop until a last user input was made (due to the blocking nature of nextLine()
).
Closing the stream seems not to be an option since I am reading from System.in
, which returns an InputStream
that is not closable.
Is there a way to interrupt the blocking of scanner, so that it will return?
thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先:这并不能解决这样的问题:如果存在未完成的输入请求(即使被取消),则需要调用 System.exit() 来关闭整个程序。您可以通过欺骗控制台击键来潜在规避此问题,但那完全是另一回事。
如果您想在控制台中执行此操作,则不进行轮询是不可能的,因为实际上不可能解除等待 System.in 输入的线程的阻塞,因为 System.in 本身没有可中断的 get() 方法。因此,如果您知道不会阻塞,则无需使用轮询来请求输入。
如果您确实想要充当控制台的可中断 nextLine() 的东西,您可能应该考虑制作一个 Swing 窗口等,并为其制作一个简单的输入界面。这实际上并不困难,并且除了一些边缘情况之外,还将具有您所要求的所有功能。
然而,我自己正在研究这个,因为我想要一种方法让线程停止等待来自 System.in 的输入,而不关闭程序(同时避免轮询),这就是我在切换到之前想到的我自己的窗户。
我不能自信地说这是最佳实践,但它应该是线程安全的,似乎工作正常,而且我想不出任何直接问题。我想将故障从备用(尽管否则无法获得)输出切换为实际错误。您可以通过中断线程或调用 cancel() 来取消活动的输入请求,这会取消当前等待的请求。
它使用信号量和线程创建一个阻塞的 nextLine() 方法,该方法可以在其他地方中断/取消。取消并不完美 - 例如,您只能取消当前等待线程的请求,但中断线程应该可以正常工作。
To start off with: this will not solve the issue that, to close the whole program, requires a System.exit() call if there has been an unfulfilled input request (even if canceled). You could potentially circumvent this by spoofing a keystroke into console, but that's a whole other ball park.
If you want to do it in console, is impossible to do without polling, as it's impossible to actually un-block a thread waiting for input from System.in, as System.in itself does not have interruptible get() methods. Because of this, without using polling to only request input if you know it will not be blocking.
If you truely want something that will act as an interruptible nextLine() for a console, you should probably look into making a Swing window, or the like, and making a simple input interface for it. This isn't really difficult, and would have all the functionality you're asking for, outside of some edge cases.
However, I was working on this myself, as I wanted a way for a thread to stop waiting for input from System.in, without closing the program (and while avoiding polling), and this is what I came up with, before switching to my own window.
I can't say with any confidence it's best-practice, but it should be thread-safe, seems to be working fine, and I can't think of any immediate issues. I would like to switch failures from alternate (albeit, otherwise unobtainable) outputs, to actual errors though. You can cancel active requests for input either by interrupting the thread, or by calling cancel(), which canceles the currently waiting request.
It uses Semaphores and threads to create a blocking nextLine() method that can be interrupted/canceled elsewhere. Canceling is not perfect - you can only cancel the currently waiting thread's request, for instance, but interrupting threads should work fine.
当然。使用核武器。在主线程结束时调用 System.exit(0) 。这会谋杀一切。甚至活动线程也在 System.in 中等待。
问题是 System.in 是一个传统的阻塞输入流,当它阻塞时,线程被标记为正在运行。你不能打断它。因此,无论您使用什么线程来读取 System.in,都会调用 read,并且 read 将阻塞该线程。你可以用一堆技巧来哄骗这些东西,避免调用 read ,除非我们可以确定不会出现阻塞,然后不断轮询。但是,没有真正的方法可以解决这个问题:任何尝试读取都会锁定您的线程,并且无论关闭多少底层流或中断或停止线程都无法拯救您。但是,如果你谋杀了整个虚拟机……线程就会死亡。
显然,您需要确保其余线程已正确退出,而这只是一个愚蠢的事情,我希望能够响应最后一个挂机的键入输入线程。但是,如果完全是这种情况,正确的答案是退出,或者至少,基本上是唯一可以在不无故燃烧时钟周期的情况下工作并让程序终止的答案。
Sure. Use a nuke. Call
System.exit(0)
at the end of your main thread. This will murder everything. Even the active thread waiting in System.in.The problem is that System.in is a traditional input stream with blocking, and when it's blocking the thread is marked as running. You cannot interrupt it. So whatever thread you are using to read the System.in is calling read and the read will block the thread. You can coax some of this stuff with a bunch of tricks avoid calling read except in those cases when we can be sure there will be no block and then constantly poll. But, there's no real way around the problem that any attempt to read that will lock your thread and no amount of closing underlying streams or interrupting or stopping the thread will save you. But, if you murder the entire vm... the thread will die.
Obviously you need to make sure the rest of the threads have properly exited and it's just that one stupid I want to be able to respond to typed input thread that is the last hanger-on. But, if that's totally the case the correct answer is to exit, or at least, basically the only answer that'll work without burning clock-cycles for no reason and let the program terminate.
这篇文章描述了一种避免阅读时阻塞的方法。它提供了代码片段,您可以按照我在评论中指出的方式进行修改。
您可以直接使用此代码,也可以编写一个新的可关闭的 InputStream 类,包装本文中描述的逻辑。
This article describes an approach to avoiding blocking when reading. It gives the code snippet, which you could amend as I indicate in a comment.
You could either use this code directly, or write a new closable InputStream class, wrapping up the logic described in this article.