私もこのサイトは初めてなので、この質問を間違った場所や何かに投稿した場合はご容赦ください:)
私は、作成した 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");
}
}
}
}