web-dev-qa-db-ja.com

Javaのブロッキング読み取り操作で待機しているスレッドを停止するにはどうすればよいですか?

次のコードを実行するスレッドがあります。

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);
    }
}

ここで、inSystem.inです。どうすればそのようなスレッドを正常に停止できますか? System.inを閉じることも、Thread.interruptを使用することも機能していないようです。

20
vitaut

これは、System.in(InputStream)の読み取りがブロッキング操作であるためです。

ここを見てください タイムアウトでInputStreamから読み取ることは可能ですか?

8
PeterMmm

あなたは9歳に出くわしました バグ 誰も直そうとはしません。 このバグレポート にはいくつかの回避策があると言われています。ほとんどの場合、タイムアウトを設定する他の方法を見つける必要があります(ビジーウェイトは避けられないようです)。

7
Denis Tulskiy

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...
2
Paolo

他のスレッドでストリームを閉じるのは安全ですか?わたしにはできる。この場合、in.read(...)は例外SocketExceptionをスローします。

1
tdx

今日も同じ問題が発生しました。これが、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
            }
        }
    }
}
1
Nans

ユーザーにデータを入力する時間を与えたい場合(デフォルト値をオーバーライドしたり、自動化されたプロセスを中断したりできるようにするため)、最初に待機し、一時停止後に使用可能な入力を確認します。

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
Andreas_D