2014-12-04 3 views
4

У меня есть многопоточное консольное приложение, которое вводится из двух разных источников. Один пользователь вводит в консоль, а другой - сеть. Я использую BufferedReader.readline(), чтобы получить вход от пользователя и что блоки, что хорошо, если я не получаю сетевой ввод, пока я жду. В этом случае мне нужно разблокировать пользовательский поток, отменив readline().В Java можно повторно открыть System.in после его закрытия

Я решил, что лучший способ отменить это, чтобы закрыть System.in и сделать readline() выбросить исключение. После этого, хотя мне нужно будет снова открыть его. Это возможно?

+0

я думаю, что его нет. – Secondo

+0

Можно утверждать, что [вы никогда не должны закрывать 'System.in', поскольку вы его не открыли] (http://stackoverflow.com/a/7457737/545127). – Raedwald

ответ

7

Невозможно повторно открыть System.in, System.out или System.err. Основными исходными потоками являются файловые дескрипторы, подключенные к другим процессам или файлы, чья личность не может распознать ваше приложение. После того, как базовые дескрипторы файла будут закрыты, их невозможно повторно открыть.

Лучшее, что я могу предложить, это создать оболочку InputStream класса для объекта System.in и кодировать оболочку для обработки close() как нет-op. Или, возможно, установить оболочку в «закрытое» состояние без фактического закрытия обернутого потока.

В вашем конкретном прецеденте это не будет работать, потому что вам нужно «разблокировать поток, который заблокирован при чтении с System.in. Поэтому в вашем случае вам нужно будет делать неблокирующий ввод от System.in. Например, используйте метод available(), чтобы проверить, есть ли какие-либо символы для чтения с консоли. (Обычно можно с уверенностью предположить, что если available() вернет число, большее нуля, вы сможете прочитать всю строку.)

(Он также может реализовать неблокирующие чтения с помощью Selector, но я не знаю «т думаю, что можно получить„выбираемый канал“для System.in объекта.)


Обратите внимание, что Thread.interrupt() не будет работать. Согласно javadocs, он будет работать, только если вы читаете с прерывистого канала.

  • System.in не является прерываемой канал, и

  • , если он был, то документально поведение для interrupt() является то, что канал закрывается прерыванием.

+0

, но user1379635 хотел использовать функцию close() для прерывания потока.что делает его не-op, этого не будет, поэтому нет необходимости называть close() :) установка обертки в «закрытом» состоянии не прерывает поток блоков. – slipperyseal

+0

Спасибо за ваш ответ. Похоже, мне придется немного перепроектировать. – ForeverNoobie

1

У меня такая же проблема, и я нашел это странным, мягко говоря,, что эта проблема не адресован самой Java: мы не хватает чего-то?

во всяком случае, благодаря Стивену C, и здесь есть небольшой пример использования его идей с анонимным классом (встроенной, при создании сканера для System.in)

(я использовал FilterInputStream вместо InputStream, так что я мог бы передать System.in конструктору)

надеюсь, что это какой-то пользы вам

public class MultiopenScanner { 
    public static int scanInt() throws IOException{ 
     //Scanner sc = new Scanner(System.in); 
     Scanner sc = new Scanner(new FilterInputStream(System.in){public void close(){}}); 
     int res = sc.nextInt(); 
     sc.close(); 
     return res; 
    } 

    public static void main(String[] args) throws IOException { 
     int i=1; 
     while (i>0) { 
      System.out.println("Give me an int please : "); 
      //some might need this : System.out.flush(); 
      i = scanInt(); 
      System.out.println("got "+i); 
     } 
     System.out.println("done"); 
    } 
} 
Смежные вопросы