首先,我正在学习 scala 和 Java 世界的新手。
我想创建一个控制台并将此控制台作为可以启动和停止的服务运行。
我能够将 ConsoleReader 运行到 Actor 中,但我不知道如何正确停止 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
}
}
我也在寻找有关此代码的任何建议!
最佳答案
从输入中读取字符的底层调用是阻塞的。在非 Windows 平台上,它将使用 System.in.read()
在 Windows 上它将使用 org.fusesource.jansi.internal.WindowsSupport.readByte
.
因此,您面临的挑战是在您想要停止控制台服务时使该阻塞调用返回。见 http://www.javaspecialists.eu/archive/Issue153.html和 Is it possible to read from a InputStream with a timeout?对于一些想法......一旦你弄清楚了,有read
返回 -1
当您的控制台服务停止时,ConsoleReader
认为它已经完成了。您需要 ConsoleReader
使用该调用的版本:
tools.jline.AnsiWindowsTerminal
并使用 ConsoleReader
采用 Terminal
的构造函数(否则 AnsiWindowsTerminal
将直接使用 WindowsSupport.readByte`)ConsoleReader
采用 InputStream
的构造函数,您可以提供自己的包装器 System.in
还有一些想法:
scala.Console
对象已经,所以为了减少混淆,你的名字不同。 System.in
是一种独特的资源,因此您可能需要确保只有一个调用者使用 Console.readLine
一次。现在start
直接调用readLine
多个来电者可以调用start
.大概控制台服务可以readLine
并维护一个处理程序列表。 关于scala - 如何取消 ConsoleReader.readLine(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6723047/