3

ユーザー入力を読み取り、ネットワーク経由で送信するスレッドがあります。スレッドは次のようにループします。

sin = new Scanner(System.in);

while (sin.hasNextLine()) {
    if (this.isInterrupted())
        break;

    message = sin.nextLine();

    // do processing...        
}

hasNextLine()しかし、スレッドを中断しようとすると、メソッドは終了しません。

このループを実際に終了するにはどうすればよいですか?

4

4 に答える 4

6

を以下の方法に置き換えてみてくださいsin.hasNextLine。その背後にある考え方は、そのストリームに利用可能なデータがない限り、ブロッキング読み取り操作に入らないことです。

少し前に同じ問題が発生しましたが、これで修正されます。基本的に、あるスレッドで実行System.in.read()中に別のスレッドから中断しようとすると、 を押さないと動作しませんEnter。os (または jvm のハードウェア抽象化レイヤー) 内の読み取り操作は完全な行のみを返すように見えるため、任意の文字を押すと機能するはずだと思うかもしれませんが、そうではありません。

私の知る限りSystem.in.available()、押さない限り、ゼロ以外の値を返すことさえありません。Enter

private boolean hasNextLine() throws IOException {
    while (System.in.available() == 0) {
        // [variant 1
        try {
            Thread.currentThread().sleep(10);
        } catch (InterruptedException e) {
            System.out.println("Thread is interrupted.. breaking from loop");
            return false;
        }// ]

        // [variant 2 - without sleep you get a busy wait which may load your cpu
        //if (this.isInterrupted()) {
        //    System.out.println("Thread is interrupted.. breaking from loop");
        //    return false;
        //}// ]
    }
    return sin.hasNextLine();
}
于 2013-10-02T06:38:40.983 に答える
0

while ループを停止する場合は、ブール値を使用して false に設定できます。

sin = new Scanner(System.in);
boolean = runLoop = true;
while (sin.hasNextLine() && runLoop) {
    if (this.isInterrupted())
        break;

    message = sin.nextLine();

    // do processing...        
}
于 2013-10-02T07:04:50.370 に答える
-1

私のテストはあなたの調査結果を裏付けていないようです。期待どおりに動作しています!

次のデモコードを書きました

public class DemoThread extends Thread {

    Scanner sin = new Scanner(System.in);

    @Override
    public void run() {
        while (sin.hasNextLine()) {
            if(this.isInterrupted()) {
                System.out.println("Thread is interrupted.. breaking from loop");
                break;
            }

            String message = sin.nextLine();
            System.out.println("Message us " + message);

            // do processing...
        }
    }

    public static void main(String args[]) throws InterruptedException {

        DemoThread thread = new DemoThread();
        thread.start();
        Thread.sleep(5000);
        thread.interrupt();

    }

}

そして出力は

a
Message us a
s
Message us s
asd
Thread is interrupted.. breaking from loop

ですので、再度ご確認ください。また、出力 asd と混同している場合は、スレッドが中断されなかった時点での前のループ反復からの文字列入力です。あなたがそれをしたくないなら、あなたはすることができます

if(!this.isInterrupted()) {
    String message = sin.nextLine(); 
}

Why is this happening?

反復でスレッドが中断されていないため、while ループに入ります (前の反復で読み取られた文字列のため、hasNext() が通過します)。次の行へ (stdinput から新しい文字列をスキャンします)。ここで、スレッドが中断されたとしましょう。プログラムは、文字列を入力するまで待機します(コンソールでEnterキーを押す必要があります)。したがって、スレッドが中断されていない場合でも、文字列が読み取られ、この文字列が hasNext() 操作 (true と評価される) を評価するために使用され、コンテキストが while ループに入ります。

これを回避するには、if(!this.isInterrupted()) ステートメント内の文字列を読み取る必要があります。上記のコードを参照してください。

于 2013-10-02T06:07:09.657 に答える
-1

通常、スレッドを無期限に実行したいが、それでも中断できるようにしたい場合は、次のようにします。

while (!Thread.currentThread().isInterrupted()) {
  while (scanner.hasNextLine()) {
    ...
  }
}
于 2013-10-02T06:08:20.990 に答える