如何取消ConsoleReader.readLine()
首先,我正在学习scala,并且是java世界的新手。 我想创建一个控制台并将该控制台作为可以启动和停止的服务运行。 我能够在 Actor 中运行 ConsoleReader,但我不知道如何正确停止 ConsoleReader。 这是代码:
import eu.badmood.util.trace
import scala.actors.Actor._
import tools.jline.console.ConsoleReader
object Main {
def main(args:Array[String]){
//start the console
Console.start(message => {
//handle console inputs
message match {
case "exit" => Console.stop()
case _ => trace(message)
}
})
//try to stop the console after a time delay
Thread.sleep(2000)
Console.stop()
}
}
object Console {
private val consoleReader = new ConsoleReader()
private var running = false
def start(handler:(String)=>Unit){
running = true
actor{
while (running){
handler(consoleReader.readLine("\33[32m> \33[0m"))
}
}
}
def stop(){
//how to cancel an active call to ConsoleReader.readLine ?
running = false
}
}
我也在寻找有关此代码的任何建议!
first of all, i'm learning scala and new to the java world.
I want to create a console and run this console as a service that you could start and stop.
I was able to run a ConsoleReader into an Actor but i don't know how to stop properly the ConsoleReader.
Here is the code :
import eu.badmood.util.trace
import scala.actors.Actor._
import tools.jline.console.ConsoleReader
object Main {
def main(args:Array[String]){
//start the console
Console.start(message => {
//handle console inputs
message match {
case "exit" => Console.stop()
case _ => trace(message)
}
})
//try to stop the console after a time delay
Thread.sleep(2000)
Console.stop()
}
}
object Console {
private val consoleReader = new ConsoleReader()
private var running = false
def start(handler:(String)=>Unit){
running = true
actor{
while (running){
handler(consoleReader.readLine("\33[32m> \33[0m"))
}
}
}
def stop(){
//how to cancel an active call to ConsoleReader.readLine ?
running = false
}
}
I'm also looking for any advice concerning this code !
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
从输入读取字符的底层调用是阻塞的。在非 Windows 平台上,它将使用 System.in.read() ,在 Windows 上它将使用 org.fusesource.jansi.internal.WindowsSupport.readByte 。
因此,您面临的挑战是当您想要停止控制台服务时导致阻塞调用返回。请参阅 http://www.javaspecialists.eu/archive/Issue153.html 和 < a href="https://stackoverflow.com/questions/804951/is-it-possible-to-read-from-a-java-inputstream-with-a-timeout">是否可能从具有超时的 InputStream 读取? 一些想法...一旦你弄清楚了,当你的控制台服务停止时,让
read
返回-1
,这样ConsoleReader
就认为已经完成了。您需要ConsoleReader
才能使用您的该调用版本:tools.jline.AnsiWindowsTerminal
并使用ConsoleReader
构造函数需要一个Terminal
(否则AnsiWindowsTerminal
将直接使用 WindowsSupport.readByte`)InputStream
的ConsoleReader
构造函数,您可以为System.in
提供自己的包装器还有一些想法:
scala .Console
对象已经存在,因此为了减少混乱,请以不同的方式命名您的对象。System.in
是一种独特的资源,因此您可能需要确保一次只有一个调用者使用Console.readLine
。现在start
将直接调用readLine
并且多个调用者可以调用start
。也许控制台服务可以readLine
并维护处理程序列表。The underlying call to read a characters from the input is blocking. On non-Windows platform, it will use
System.in.read()
and on Windows it will useorg.fusesource.jansi.internal.WindowsSupport.readByte
.So your challenge is to cause that blocking call to return when you want to stop your console service. See http://www.javaspecialists.eu/archive/Issue153.html and Is it possible to read from a InputStream with a timeout? for some ideas... Once you figure that out, have
read
return-1
when your console service stops, so thatConsoleReader
thinks it's done. You'll needConsoleReader
to use your version of that call:tools.jline.AnsiWindowsTerminal
and use theConsoleReader
constructor that takes aTerminal
(otherwiseAnsiWindowsTerminal
will just use WindowsSupport.readByte` directly)ConsoleReader
constructor that takes anInputStream
, you could provide your own wrapper aroundSystem.in
A few more thoughts:
scala.Console
object already, so for less confusion name yours differently.System.in
is a unique resource, so you probably need to ensure that only one caller usesConsole.readLine
at a time. Right nowstart
will directly callreadLine
and multiple callers can callstart
. Probably the console service canreadLine
and maintain a list of handlers.假设 ConsoleReader.readLine 响应线程中断,您可以重写 Console 以使用一个线程,然后您可以中断该线程来停止它。
Assuming that ConsoleReader.readLine responds to thread interruption, you could rewrite Console to use a Thread which you could then interrupt to stop it.
您可以覆盖您的 ConsoleReader 输入流。恕我直言,这是合理的,因为 STDIN 是一个“慢”流。请根据您的需要改进示例。这只是草图,但它可以工作:
使用 InputStream 包装器:
}
PS 我尝试使用 NIO - System.in 有很多麻烦(尤其是跨平台)。我又回到了这个变体。 CPU 负载接近 0%。这适合这种交互式应用。
You may overwrite your ConsoleReader InputStream. IMHO this is reasonable well because of STDIN is a "slow" stream. Please improve example for your needs. This is only sketch, but it works:
with InputStream wrapper:
}
P.S. I tried to use NIO - a lot of troubles with System.in (especially crossplatform). I returned to this variant. CPU load is near 0%. This is suitable for such interactive application.