Java ScheduledThreadPoolExecutor运行延迟15毫秒/时间不一致?

Java ScheduledThreadPoolExecutor运行延迟15毫秒/时间不一致?,java,multithreading,time,threadpool,Java,Multithreading,Time,Threadpool,我也是这个网站的新成员,所以如果我在错误的地方发布了这些问题,请原谅:) 我一直在不停地研究和创建测试程序,试图找出我创建的ScheduledThreadPoolExecutor可能出了什么问题 问题: 运行下面的测试应用程序时,ScheduledThreadPoolExecutor计划以3毫秒的固定速率运行,但运行混乱,频繁出现超过15毫秒的峰值。它应该每3毫秒执行一次 有趣的细节: 问题仅发生在IDE之外,ScheduledThreadPoolExecutor在诸如Netbeans或Inte

我也是这个网站的新成员,所以如果我在错误的地方发布了这些问题,请原谅:)

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

问题:

运行下面的测试应用程序时,ScheduledThreadPoolExecutor计划以3毫秒的固定速率运行,但运行混乱,频繁出现超过15毫秒的峰值。它应该每3毫秒执行一次

有趣的细节:

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

问题:

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

配置:

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

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

谢谢大家的帮助!:)


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

JVM支持几种不同的方法。延迟和吞吐量之间存在折衷

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


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

我认为Windows计时器没有这么好的分辨率。如果您在Google上搜索该主题的更多信息,则从技术上讲,计时器和ScheduledExecutor接口指定的契约不能保证任务将在指定的时间间隔内准确执行。他们只是承诺不会在间隔时间之前运行它们。

使用IDE(Eclipse)进行测试后,我同意您的发现(唯一标记的是3-4ms),欢迎使用SO+谢谢大家:)@AlexColeman谢谢你们的测试。这与我在IDE中得到的结果相同,但在命令提示符下运行的IDE之外,我得到的峰值大于15毫秒,这更糟糕。否则我就忽略了小的时间变化。我不知道为什么它们在IDE内外都不同。@neptune692与命令行相比,您在IDE中使用的是不同的Java版本还是类似版本的版本?您的机器上有其他版本的Java吗?如果您确实尝试通过命令行在其他版本中编译,并查看它是否只在另一个版本上运行。例如,我用Java6编译了您的示例,并用Java7(命令行)运行,发现了明显的区别。然而,当我通过命令行在Java6中运行时,它看起来更稳定。虽然这可能只是巧合,但我会+1,但我记得有一位同事做过测试,测试表明Windows中的低分辨率计时器问题在Win7和可能的Vista中得到了修复。我同意这可能是GC问题的评估。这是非常有希望的,但是在命令提示符下运行添加的命令后,似乎并没有太多的修复问题。我一开始以为可以,但我在IDE中测试不正确,而不是在命令提示符下。ScheduledThreadPoolExecutor仍然有15毫秒的频繁峰值,而它应该是3毫秒。如果它不是一个很大的变化,并且在IDE中运行时没有被修复,我会忽略它,这很奇怪。不过,感谢您的回答:)另一方面,我没有尝试将该命令添加到IDE中,因为出于某种原因,该问题在IDE中没有出现,我在命令提示符
java-Xincgc-jar SpeedTest.jar
中尝试了它,并得到了相同的结果。想要更奇怪的是,如果我在运行编译后的桌面版本时从IDE运行,那么问题已经解决,可以从命令提示符运行。因此,如果IDE中的某个应用程序同时运行,则问题会在桌面版本中消失,请从命令提示符处运行。。。。15毫秒的尖峰消失了。。。我甚至不知道从哪里开始。你能看到用于从IDE启动进程的命令行吗?用“ps aux”还是什么?是否有特殊选项?是否有人可以验证他们在IDE之外也遇到了此问题?在它的范围内只有1毫秒,这是完全可以接受的,但在它的范围外,峰值为15毫秒,这是远远不够的:/如果您确实测试它,请确保IDE版本没有在同一时间运行,因为它以某种方式修复了它。
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");
            }
        }
    }
}