Параллельный / неблокирующий ввод с консоли
Я работаю над MUD в Java. Я читаю ввод игрока каждый тик, но я использую Scanner
который использует блокирующие операции. Я хочу иметь неблокирующий ввод.
Я посмотрел на nio
пакет, который имеет Selector
класс, но я не уверен, как использовать его в отношении System.in
, Я полагаю, что он мне определенно понадобится после запуска сервера, но сейчас все в автономном режиме.
Я пытался расширить основной класс от Applet
и переопределение keyDown
, но это просто означало, что входные данные больше не принимаются после первого. Конечно, я больше ничего не блокировал, но тогда больше не было ввода. keyDown
мне никогда больше не звонили
Возможно, потоки могут быть прерваны, даже если они выполняют операции блокировки?
Спасибо за понимание этой проблемы.
4 ответа
Вы не можете сделать это с системной консолью, потому что сейчас это не может быть сделано многоплатформенным способом.
Вы можете использовать Swing Window в качестве консоли или найти подход, основанный на JNI, но он может не работать на некоторых платформах.
Вы можете использовать JCurses. Это может работать, оно основано на JNI и поддерживает Windows и Linux.
keyDown() устарела, поэтому я бы предложил вместо этого использовать processKeyEvent и keyListener.
Возможно, потоки могут быть прерваны, даже если они выполняют операции блокировки?
Да, если у вас есть ссылка на объект потока, который вы хотите прервать, вы можете просто вызвать метод interrupt() для этого экземпляра. И в методе выполнения потока вы можете обработать прерванное исключение. Тем не менее, это кажется немного взломать. Я не понимаю, как это более полезно, чем использование простого KeyListener.
JLine также может соответствовать вашим требованиям:
http://jline.sourceforge.net/apidocs/src-html/jline/ConsoleReader.html
Мне пришлось решить аналогичную проблему с блокировкой записи / чтения из 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 ...