【问题标题】:Java ScheduledThreadPoolExecutor running 15 milliseconds late / inconsistent time?Java ScheduledThreadPoolExecutor 运行延迟 15 毫秒/时间不一致?
【发布时间】:2012-08-03 21:36:38
【问题描述】:

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

我一直在研究和创建测试程序,试图找出我创建的 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");
            }
        }
    }
}

【问题讨论】:

  • 在使用 IDE (Eclipse) 进行测试后,我同意您的发现(唯一标记为 3-4 毫秒)
  • 欢迎来到 SO。 +1 写得很好的问题。
  • 谢谢大家 :) @AlexColeman 感谢您的测试。这与我在 IDE 中得到的结果相同,但在命令提示符下运行的结果之外,我得到的峰值大于 15 毫秒,而且情况更糟。否则我会忽略小的时间变化。我不知道为什么它们在 IDE 内外有所不同。
  • @neptune692 与命令行相比,您是否在 IDE 中使用不同的 Java 版本或类似版本的发行版?
  • 您的机器上有其他版本的 Java 吗?如果您确实尝试通过命令行在其他版本中进行编译,并查看仅在其他版本上运行时是否会发生这种情况。例如,我在 Java 6 中编译了您的示例并使用 Java 7(命令行)运行并看到了明显的差异。但是,当我通过命令行在 Java 6 中运行时,它似乎更加稳定。虽然这可能只是一个巧合

标签: java multithreading time threadpool


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我认为 Windows 计时器根本没有这么好的分辨率。如果您 Google http://www.google.de/search?q=windows+timer+resolution

    ,您会找到有关该主题的更多信息

    【讨论】:

    • 我会 +1,但我记得一位同事正在做测试,结果表明 Windows 中的低分辨率计时器问题已在 Win7 和可能的 Vista 中修复。
    【解决方案3】:

    我认为您的问题来自垃圾收集器,它会定期冻结进程以从内存中删除未使用的对象。

    JVM 支持几种不同的GC algorithms。在延迟和吞吐量之间进行权衡。

    可能 IntelliJ 使用低暂停 GC 来支持 UI 快速响应,而 JVM 在 IDE 之外默认使用高吞吐量。

    您可以尝试在您的项目中添加-Xincgc 选项(以选择并发标记和扫描)吗?

    【讨论】:

    • 我同意这可能是 GC 问题的评估。
    • 这很有希望,但是在命令提示符中使用添加的命令运行它之后,它似乎并不能解决问题。起初我认为它确实如此,但我在 IDE 中而不是在命令提示符中错误地测试了它。 ScheduledThreadPoolExecutor 在它应该是 3 时仍然有 15 毫秒的频繁峰值。如果它不是那么大的变化并且在 IDE 中运行时没有修复,我会忽略它,这很奇怪。不过还是谢谢你的回答:)
    • 另一方面,我没有尝试将命令添加到 IDE,因为由于某种原因,问题不会在 IDE 内部发生,我在命令提示符下尝试过java -Xincgc -jar SpeedTest.jar 并得到了相同的结果。想要更奇怪的是,如果我在运行已编译的桌面版本时从 IDE 运行,则从命令提示符运行该问题已得到修复。因此,如果 IDE 中的应用程序同时运行,则问题在从命令提示符运行的桌面版本中消失...... 15 毫秒的尖峰消失......我什至不知道从哪里开始这个事实.
    • 你能看到用于从 IDE 启动进程的命令行吗?用“ps aux”什么的?有什么特别的选择吗?
    • 任何人都可以验证他们在 IDE 之外也遇到了这个问题吗?在它里面的范围只有 1 毫秒,完全可以接受,但在外面它会飙升到 15 毫秒,这是很远的:/ 如果你测试它,只需确保 IDE 版本没有同时运行,因为它会以某种方式修复它。跨度>
    猜你喜欢
    • 1970-01-01
    • 2015-07-12
    • 2015-11-06
    • 2011-12-28
    • 1970-01-01
    • 1970-01-01
    • 2016-10-04
    • 2019-09-22
    • 2017-09-03
    相关资源
    最近更新 更多