并发/非阻塞控制台键盘输入
Posted
技术标签:
【中文标题】并发/非阻塞控制台键盘输入【英文标题】:Concurrent/Non-blocking console keyboard input 【发布时间】:2011-01-16 00:29:36 【问题描述】:我正在用 java 开发一个 MUD。我每次都读取玩家输入,但我使用的是使用阻塞操作的Scanner
。我想要非阻塞输入。
我查看了nio
包,它有一个Selector
类,但我不确定如何使用它来处理System.in
。我想我在运行服务器后肯定会需要它,但现在一切都处于离线状态。
我尝试从Applet
扩展主类并覆盖keyDown
,但这只是意味着在第一个之后不再接受输入。当然,我不再阻止任何东西,但是没有更多的输入。我猜keyDown
再也没有接到过电话。
也许线程即使在执行阻塞操作时也会被中断?
感谢您对此问题的任何见解。
【问题讨论】:
非阻塞套接字(网络)的完成方式与非阻塞 IO 不同,至少在大多数环境中不同。 【参考方案1】:你不能用系统控制台来做这件事,因为现在它不能用多平台的方式来做。
您可以将摇摆窗口用作控制台或查找基于 JNI 的方法,但它可能不适用于某些平台。
您可以使用JCurses。它可能会工作,它基于 JNI 并支持 Windows 和 Linux。
【讨论】:
JCurses 是在 UNIXcurses
上构建的,所以它肯定可以工作。
截至 2014 年 5 月 23 日,explanation
链接已失效(现在链接到域停放页面)。
@daveloyall 我删除了它。谢谢。【参考方案2】:
keyDown() 是deprecated,所以我建议改用processKeyEvent 和keyListener。
也许线程在执行阻塞操作时也会被中断?
是的,如果您有要中断的线程对象的引用,您可以简单地在该实例上调用interrupt() 方法。并且在线程的run方法中你可以处理被中断的异常。但是,这似乎有点hack-ish。我看不出这比使用简单的 KeyListener 更有帮助。
【讨论】:
Thread.interrupt() 仅设置中断标志并在线程处于睡眠或阻塞状态时唤醒它。它不会中断套接字读取的常规阻塞文件 IO。它也不会中断繁重的计算或自旋锁 - 您的代码需要检查并遵守“中断”标志才能被中断。【参考方案3】:JLine 也可能适合您:
http://jline.sourceforge.net/apidocs/src-html/jline/ConsoleReader.html#line.1447
【讨论】:
downvote:以上链接指向ConsoleReader.readVirtualKey
,这是一个阻塞操作。【参考方案4】:
我不得不通过阻止从 http 写入/读取来解决类似的问题。在那种特殊情况下,我使用了本地缓冲区和线程。
想法很简单,一个线程从标准输入读取并将内容放入缓冲区。第二做同样的写作。
然后您在缓冲区中使用非阻塞查询。
示例代码:
class NonBlockingReader implements Runnable
Reader in;
List buffer;
public void run()
String line=null;
while((line=in.readLine())!=null)
storeLine(line);
private synchronized storeLine(String line)
buffer.add(line);
public synchronized String getLine()
if(list.size()>0)
return list.removeFirst();
return null;
// .. same for writer, then you jast pass stdin and stdout ...
【讨论】:
System.in 流是 Java 的标准输入等效项被缓冲,因此应用程序在用户按下回车之前看不到字符。以上是关于并发/非阻塞控制台键盘输入的主要内容,如果未能解决你的问题,请参考以下文章