0

次のスニペットは、「Foo」という名前のスレッドで、1 分間スリープし、1 分間に入力されたデータをログ ファイルにコピーします

         while(isStarted) {
           try {
              Thread.sleep(60000); // sleep for 1 minute
              ArrayList<String> keyStrokeList = nativeMethods.getKeyStrokeList();
              int result = copy.copyToLogFile(keyStrokeList);
              System.out.println(result);
           } catch(Exception exc) {
               exc.printStackTrace();
             }
         }

1 つの状況について説明します。

fooスレッドは、過去 1 分間に入力されたすべてのデータのコピーを完了し、スリープ状態になってから 30 秒が経過しました。このスレッドは、スリープ中にいくつかのキーがタップされている状況を認識していないため、 を押したときにキーストロークをログファイルにコピーすることはできませんSystem.exit(0)

このスレッドを中断する方法はありますか。つまり、スレッドを起動して、データをログ ファイルにコピーするように依頼してください

この問題にどのように取り組むべきか議論してください。

質問の状況:

loop started

thread is sleeping and will sleep for 1 minute

after a minute,it gets the keys tapped in the last 1 minute and copies all that
to a file

Thread sleeps again..and will sleep for 1 minute before it copies the keystrokes

It has been about 30 seconds and thread will sleep for 30 seconds more before it starts
copying the key strokes

suddenly the user presses exit button in the application

The user wants that key strokes be recorded till the second he presses exit

I cannot do System.exit(0) before checking the thread is asleep or not

How do I do this. Should I awake it or make a different call to the list and get the 
key strokes because they are being recorded ? And how shall I awake it ?
4

3 に答える 3

1

あなたはそこまでの道のりです...

while(isStarted) {
    try {
        Thread.sleep(60000); // sleep for 1 minute
    } catch(InterruptedException exc) {
        exc.printStackTrace();
    }
    ArrayList<String> keyStrokeList = nativeMethods.getKeyStrokeList();
    int result = copy.copyToLogFile(keyStrokeList);
    System.out.println(result);
}

必要なのは、ループを終了する方法を提供することです...

public void dispose() {
    isStarted = false;
    interrupt();
    try {
        join();
    } catch(InterruptedException exc) {
        exc.printStackTrace();
    }
}

また、すべての非デーモン スレッドが完了するまで (通常のシャットダウンで) JVM が終了しないことも知っておく必要があります。これは、呼び出すことができSystem.exit(0)、ロガー スレッドが終了するまで JVM が終了しないことを意味します。

これを使用することもできますが、ロガースレッドでメソッドを呼び出す能力を持つシャットダウンフックを取り付ける...dispose

于 2012-10-07T10:32:16.570 に答える
0

これを行う方法を示すかなり単純なテスト ケースを次に示します。

public class InterruptTest
{
    @Test
    public void test() throws InterruptedException
    {
        //Create the logging thread and start it
        LogRunnable runnable = new LogRunnable();
        Thread t = new Thread(runnable);
        t.start();

        //Wait some time
        Thread.sleep(3500);

        System.out.println("User has pressed exit, starting shutdown");

        //Tell the runnable to shut down
        runnable.halt();
        //Interrupt the thread to wake it up
        t.interrupt();
        //Wait until thread terminates
        t.join();

        System.out.println("Exiting");
    }

    private static class LogRunnable implements Runnable
    {
        private static final int SLEEPMS = 2000;

        private boolean isStarted = true;
        private int runCount = 1;

        public void halt()
        {
            this.isStarted = false;
        }

        public void run()
        {
            while(isStarted)
            {
                try
                {
                    Thread.sleep(SLEEPMS);
                }
                catch(InterruptedException e)
                {
                    System.out.println("Interrupted");
                }
                catch(Exception exc)
                {
                    exc.printStackTrace();
                }

                //Do work
                System.out.println("Work done " + runCount++);
            }
        }
    }
}

出力:

Work done 1
User has pressed exit, starting shutdown
Interrupted
Work done 2
Exiting
  • ユーザーが終了キーを押すと、メイン スレッドにシグナルを送り、すべてのシャットダウンを開始します (テスト ケースでは、しばらく待機するだけです)。
  • ロギング スレッドは、interrupt()呼び出しを介して停止し、起動するように指示されます。
  • 終了する前に、メイン スレッドはjoin()を呼び出してロギング スレッドが完了するまで待機します。何か問題が発生した場合にタイムアウトを取るオーバーロードの使用を検討できます。
  • ロギング スレッドは でウェイクアップしInterruptedException、キャッチして終了した後にコードを完了します
  • ロギング スレッドが終了した後、メイン スレッドはjoin()-call から戻り、終了します。
于 2012-10-07T10:42:35.527 に答える
0

Thread.sleep(..) メソッドの代わりに、2 つのスレッド間で共有オブジェクトを使用して待機/通知パターンを実装する必要があります。

あなたの状態では、2つのスレッドがあります:

  • 1分間隔でバッファを読み取ります。(スレッド 1)
  • どちらが最初に「終了」イベントを受け取りますか。(スレッド 2)

したがって、Thread1 のインスタンスを作成するたびに、Java オブジェクト (new Object()) を渡すことができます。object.wait(60*1000); を使用して、リーダー スレッドをスリープ状態にすることができます。object.notify() が 1 分間呼び出されない場合、最大 1 分間スリープします。この間に object.notify() が呼び出された場合、スレッドはすぐに再開されます。

したがって、ユーザーがアプリケーションを終了したいときはいつでも object.notify(); を呼び出すことができます。リーダースレッドを再開します。

私の英語が下手で解決策を説明できなかった場合は、お知らせください。コードサンプルを提供します。

于 2012-10-07T10:31:31.483 に答える