4

我也是这个网站的新手,如果我在错误的地方或其他地方发布了这个问题,请原谅我:)

我一直在研究和创建测试程序,试图找出我创建的 ScheduledThreadPoolExecutor 可能出了什么问题。

问题:

在运行以下测试应用程序时,计划以 3 毫秒的固定速率运行的 ScheduledThreadPoolExecutor 会以大于 15 毫秒的频繁峰值运行混乱。它应该以每 3 毫秒的速率执行。

有趣的细节:

该问题发生在 IDE 之外,ScheduledThreadPoolExecutor 在诸如 Netbeans 或 IntelliJ 之类的 IDE 中按预期运行。

问题:

为什么使用 Timer 和 ScheduledThreadPoolExecutor 类的时间非常不一致?执行之间的时间范围从每次执行的预期 3 毫秒到执行之间的 15 毫秒的频繁峰值。

配置:

Java 7 Update 5、IntelliJ IDE、Windows 7、从命令提示符运行。

测试应用程序演示问题,确保在 IDE 之外使用以查看问题。该程序将输出大于执行之间预期时间的时间。应该在 15 毫秒左右,而不是预期的 3 毫秒。

谢谢大家的帮助!:)

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

我认为 Windows 计时器根本没有这么好的分辨率。如果您 Google http://www.google.de/search?q=windows+timer+resolution ,您会发现更多关于该主题的信息

于 2012-08-07T09:40:19.893 回答
1

从技术上讲,Timer 和 ScheduledExecutor 接口指定的合约不保证任务将在指定的时间间隔内准确执行。他们只是承诺不会在间隔时间之前运行它们。

于 2012-08-07T17:45:09.793 回答