4

私もこのサイトは初めてなので、この質問を間違った場所や何かに投稿した場合はご容赦ください:)

私は、作成した ScheduledThreadPoolExecutor で何が問題になっているのかを突き止めようと、ノンストップでテスト プログラムを調査および作成してきました。

問題:

以下のテスト アプリケーションを実行すると、3 ミリ秒の固定レートで実行するようにスケジュールされた ScheduledThreadPoolExecutor が、15 ミリ秒を超えるスパイクが頻繁に発生して無秩序に実行されます。3 ミリ秒ごとに実行する必要があります。

興味深い詳細:

この問題は IDE の外部でのみ発生します。ScheduledThreadPoolExecutor は、Netbeans や IntelliJ などの IDE 内で期待どおりに実行されます。

質問:

Timer クラスと ScheduledThreadPoolExecutor クラスを使用すると、非常に一貫性のない時間が得られるのはなぜですか? 実行間の時間は、実行ごとに予想される 3 ミリ秒から、実行間の 15 ミリ秒の頻繁なスパイクまでの範囲です。

構成:

Java 7 Update 5、IntelliJ IDE、Windows 7、コマンド プロンプトから実行。

問題を示すアプリをテストします。問題を確認するには、IDE の外部で使用してください。このプログラムは、予想される実行間隔よりも長い時間を出力します。予想される 3 ミリ秒ではなく、約 15 ミリ秒になるはずです。

ご協力ありがとうございました!:)

package testtime;

import javax.swing.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestTime extends JFrame {

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestTime().setVisible(true);
            }
        });
    }

    JTextArea area = new JTextArea();
    JScrollPane pane = new JScrollPane(area);

    ScheduledThreadPoolExecutor executor;

    public TestTime() {
        setSize(300, 300);
        setAlwaysOnTop(true);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        area.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                area.setText("--Press anywhere to start--\n\n" +
                        "If time exceeds 3 milliseconds it will be printed here...\n\n" +
                        "------------------------------------\n\n");
                executor = new ScheduledThreadPoolExecutor(1);
                executor.scheduleAtFixedRate(new Loop(), 0L, 3L, TimeUnit.MILLISECONDS);
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                executor.shutdownNow();
            }
        });

        area.setLineWrap(true);
        area.setWrapStyleWord(true);
        area.setText("--Press anywhere to start--");
        add(pane);
    }

    class Loop extends Thread {
        long time = 0L;

        @Override
        public void run() {
            long timeTaken = System.nanoTime() - time;
            time = System.nanoTime();

            if(timeTaken > 3500000L) {
                area.append(timeTaken+"(nanoseconds)  -- "+(timeTaken/1000000L)+"(milliseconds)\n");
            }
        }
    }
}
4

3 に答える 3

3

あなたの問題は、プロセスを定期的にフリーズしてメモリから未使用のオブジェクトを削除するガベージコレクターに起因すると思います。

JVM は、いくつかの異なるGC アルゴリズムをサポートしています。レイテンシとスループットの間にはトレードオフがあります。

IntelliJ は低一時停止 GC を使用して UI の迅速な応答を優先する可能性がありますが、JVM はデフォルトで IDE の外部で高スループットに設定されています。

-Xincgcオプション (Concurrent Mark&Sweep を選択する) をプロジェクトに追加してみてはいかがでしょうか?

于 2012-08-07T09:27:41.797 に答える
1

技術的には、Timer および ScheduledExecutor インターフェイスによって指定されたコントラクトは、タスクが指定された間隔で正確に実行されることを保証しません。それらは、間隔より早く実行しないことを単に約束します。

于 2012-08-07T17:45:09.793 に答える
1

Windows タイマーには、それほど細かい解像度がないと思います。Google でhttp://www.google.de/search?q=windows+timer+resolutionを検索すると、このトピックの詳細が見つかります。

于 2012-08-07T09:40:19.893 に答える