Параллельный / неблокирующий ввод с клавиатуры консоли - PullRequest
7 голосов
/ 12 февраля 2010

Я работаю над MUD в Java. Я читаю ввод игрока каждый тик, но я использую Scanner, который использует операции блокировки. Я хочу иметь неблокирующий ввод.

Я смотрел на пакет nio, который имеет класс Selector, но я не уверен, как его использовать в отношении System.in. Я полагаю, что он мне определенно понадобится после запуска сервера, но сейчас все в автономном режиме.

Я пытался расширить основной класс с Applet и переопределить keyDown, но это просто означало, что ввод больше не принимался после первого. Конечно, я больше ничего не блокировал, но тогда больше не было ввода. keyDown мне никогда больше не звонили.

Возможно, потоки могут быть прерваны, даже если они выполняют операции блокировки?

Спасибо за понимание этой проблемы.

Ответы [ 4 ]

2 голосов
/ 12 февраля 2010

Вы не можете сделать это с системной консолью, потому что сейчас это не может быть сделано многоплатформенным способом.

Вы можете использовать поворотное окно в качестве консоли или найти подход, основанный на JNI, но он может не работать на некоторых платформах.

Вы можете использовать JCurses . Он может работать, он основан на JNI и поддерживает Windows и Linux.

0 голосов
/ 17 февраля 2010

Мне пришлось решить аналогичную проблему с блокировкой записи / чтения из 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 ...
0 голосов
/ 16 февраля 2010

keyDown () равно устарело , поэтому я рекомендую использовать processKeyEvent и keyListener вместо.

Возможно, потоки могут быть прерваны, даже если они выполняют операции блокировки?

Да, если у вас есть ссылка на объект потока, который вы хотите прервать, вы можете просто вызвать метод interrupt () для этого экземпляра. И в методе выполнения потока вы можете обработать прерванное исключение. Тем не менее, это кажется немного взломать. Я не понимаю, как это более полезно, чем использование простого KeyListener.

0 голосов
/ 15 февраля 2010

JLine также может соответствовать вашему счету:

http://jline.sourceforge.net/apidocs/src-html/jline/ConsoleReader.html#line.1447

...