Как остановить поток, ожидающий в операции блокировки чтения в Java? - PullRequest
19 голосов
/ 15 ноября 2010

У меня есть поток, который выполняет следующий код:

public void run() {
    try {
        int n = 0;
        byte[] buffer = new byte[4096];
        while ((n = in.read(buffer)) != -1) {
            out.write(buffer, 0, n);
            out.flush();
        }
    } catch (IOException e) {
        System.out.println(e);
    }
}

, где in равно System.in. Как я могу остановить такую ​​нить изящно? Ни закрытие System.in, ни использование Thread.interrupt не работают.

Ответы [ 7 ]

8 голосов
/ 15 ноября 2010

Это потому, что чтение System.in (InputStream) является операцией блокировки.

Смотрите здесь Возможно ли чтение из InputStream с таймаутом?

7 голосов
/ 15 ноября 2010

Вы наткнулись на 9-летнюю ошибку , которую никто не хочет исправлять. Говорят, что в отчете об ошибке есть некоторые обходные пути. Скорее всего, вам нужно будет найти какой-то другой способ установить время ожидания (ожидание занятости кажется неизбежным).

2 голосов
/ 15 ноября 2010

Вы можете использовать метод available () (который не является блокирующим), чтобы проверить, есть ли что-нибудь для чтения заранее.

В псевдо-Java:

//...
while(running)
{
    if(in.available() > 0)
    {
        n = in.read(buffer);
        //do stuff with the buffer
    }
    else
    {
        Thread.sleep(500);
    }
}
//when running set to false exit gracefully here...
1 голос
/ 02 марта 2012

Безопасно ли закрываться в потоке в другом потоке? Меня устраивает. В этом случае in.read(...) выдает исключение SocketException.

1 голос
/ 01 марта 2012

У меня была такая же проблема сегодня, и вот как я ее исправил, используя in.ready():

public void run() {
    String line;
    // Some code

    while(!Thread.currentThread().isInterrupted()){
        try {
            if (in.ready()) {
                line = in.readLine();
            } 
        } catch (Exception e) {
            try {
                Thread.currentThread().wait(500);
            } catch (InterruptedException e1) {
                // Do what we want when thread is interrupted
            }
        }
    }
}
0 голосов
/ 15 ноября 2010

Если вы хотите дать пользователю некоторое время для ввода данных - возможно, чтобы разрешить переопределение значений по умолчанию или прерывание какого-либо автоматизированного процесса - затем сначала подождите и проверьте доступный ввод после паузы:

System.out.println("Enter value+ENTER within 5 Seconds to override default value: ");
try{
  Thread.sleep(5000);
} catch {InterruptedException e){}

try{
  int bytes = System.in.available();
  if (bytes > 0) {
    System.out.println("Using user entered data ("+size+" bytes)");
  } else {
    System.out.println("Using default value"); 
  }
} catch(IOException e) { /*handle*/ }
0 голосов
/ 15 ноября 2010

вы можете использовать внешний флаг для этого

boolean flag = true;


public void run() { 
    try { 
        int n = 0; 
        byte[] buffer = new byte[4096]; 
        while ((n = in.read(buffer)) != -1 && flag) { 
            out.write(buffer, 0, n); 
            out.flush(); 
        } 
    } catch (IOException e) { 
        System.out.println(e); 
    } 
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...