10

いくつかのことを別々に行う別のバックグラウンドスレッドを作成することは可能ですか?次のプログラムを試しましたが、期待どおりに動作しません。

public class Test {

    private static class UpdaterThread extends Thread {
        private final int TIMEOUT = 3000;

        public void run() {
            while (true) {
                try {
                    Thread.sleep(TIMEOUT);
                    System.out.println("3 seconds passed");
                } catch (InterruptedException ex) {
                }
            }
        }
    }

    /**
     * @param args
     *            the command line arguments
     */
    public static void main(String[] args) {
        try {
            Thread u = new UpdaterThread();
            u.start();
            while (true) {
                System.out.println("--");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

3秒ごとに「3秒経過」が複数の「-」文字列の流れで出力されることを期待していました。実際、「3秒経過」は印刷されません。なんで?また、メインスレッドから独立して何かを実行するバックグラウンドスレッドを作成するにはどうすればよいですか?

4

5 に答える 5

19

使用java.util.TimerTaskjava.util.Timer

Timer t = new Timer();

t.scheduleAtFixedRate(
    new TimerTask()
    {
        public void run()
        {
            System.out.println("3 seconds passed");
        }
    },
    0,      // run first occurrence immediately
    3000);  // run every three seconds
于 2012-07-17T10:44:18.197 に答える
7

「3秒経過」と表示されます。を削除するSystem.out.println("--")と、より簡単に表示されます;-)

ScheduledExecutorServiceこれで、を使用して、 :のRunnable代わりにを使用することもできます。Thread

public class Test {

    private static class Updater implements Runnable {

        @Override
        public void run() {
            System.out.println("3 seconds passed");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Runnable r = new Updater();
        ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
        service.scheduleAtFixedRate(r, 0, 3, TimeUnit.SECONDS);

        Thread.sleep(10000);
        service.shutdown();

    }
}
于 2012-07-17T10:47:44.363 に答える
3

上記のアプローチを使用して定期的に実行することができますが、TimerTaskより簡単な場合もあります。

出力に関してはUpdaterThread、非常にタイトなループになっているため、メインスレッドが実行を許可していないと思われます。これは、使用可能なCPU/コアなどに依存することに注意してください。

メインスレッドでスリープすること、またはThread.yield()を使用することを検討しましたか?そのリンクされたページの但し書きに注意してください:

いつyield()を使用しますか?

私は事実上決して言わないでしょう。その動作は標準的に定義されておらず、yield()を使用して実行する可能性のあるタスクを実行するためのより良い方法が一般的にあります。CPUの一部のみを使用しようとしている場合は、より制御可能な方法でこれを実行できます。スレッドが最後の処理チャンクで使用したCPUの量を見積もり、それを補うために一定時間スリープする方法です。sleep()メソッドを参照してください。

スレッドの中断の処理に関するこの興味深い記事にも注意してください。

于 2012-07-17T10:43:56.597 に答える
2

答えはたくさんありますが、なぜ彼の例がうまくいかなかったのか誰も言いません。System.outは出力ストリームであるため、このストリームへの書き込みを開始すると、JAVAはそれをロックし、他のすべてのスレッドはロックがストリームに適用されるまで待機します。ストリームのロックが解除されると、別のスレッドがこのストリームを操作できるようになります。

サンプルを機能させるには、メインスレッドのループに追加する必要がありThread.sleepます。while

于 2012-07-17T18:53:11.510 に答える
1

を使用することをお勧めしScheduledExecutorServiceます。UpdaterThread()3秒ごとに実行するには、次のようにします。

ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new UpdaterThread(), 0, 3000, TimeUnit.MILLISECONDS);

詳細については、Javaチュートリアル-エグゼキュータインターフェイスを参照してください。

于 2012-07-17T10:47:57.093 に答える