【问题标题】:Getting negative duration time between two long actions?在两个长动作之间获得负持续时间?
【发布时间】:2013-11-13 10:04:34
【问题描述】:

我正在使用线程查询服务器 URL,我正在计算查询该服务器并获得用作 response time 的响应所花费的时间,但有时返回的时间是负数,这应该发生了!

我可以猜想是在连接失败并且这种情况发生得如此之快的时候,但对我来说,调用两个连续的 System.nanoTime() 至少不应该低于 0 !

这是我的代码:

final long startTime = System.nanoTime();
ExecutorService executor = Executors.newFixedThreadPool(1);

Connector connector = new Connector(url);
String response = null;
Long duration = null;

try {
   Future<String> future = executor.submit(connector);
   response = future.get(Connector.timeout, TimeUnit.MILLISECONDS);

   duration = Long.valueOf(System.nanoTime() - startTime);
}
catch (Exception e) {}

executor.shutdown();

// Here, duration is sometimes negative !

还有 Connector.java :

public class Connector implements Callable<String> {
    public final static int timeout = 2500; // WE use a timeout of 2.5s, which should be enough

    private String urlStr;

    public Connector(String url) {
        this.urlStr = url;
    }

    @Override
    public String call() throws Exception {
        URL url = new URL(urlStr);

        HttpURLConnection connection = (HttpURLConnection)url.openConnection();
        connection.setConnectTimeout(timeout - 50);
        connection.setRequestMethod("GET");
        connection.setRequestProperty("User-Agent", "Mozilla/5.0 (X11; Linux i686; rv:21.0) Gecko/20100101 Firefox/21.0");
        connection.connect();

        int code = connection.getResponseCode();
        connection.disconnect();
        return String.valueOf(code);
    }
}

你知道为什么吗?

更新:在S.O. question 上,第一个答案(由 david-johnstone)的第一条评论(由@gustafc)非常有趣:

nanoTime 的一个问题(在 Windows w. Sun JDK6 上,无论如何)是 返回的值取决于执行线程的 CPU 内核如果 线程开始在一个核心上执行并在另一个核心上结束, 你的数字会有些偏离。我有像long start这样的代码= System.nanoTime();做(); long elapsedNanos = System.nanoTime() - 开始;最后以 elapsedNanos 为负数。 ——

我在 Linux Fedora 版本下运行我的机器,但也许这就是正在发生的事情。

很明显,问题出在System.nanoTime(),但我找不到更好的选择:/

【问题讨论】:

  • “长时间动作” - 多长时间?如果我没记错的话.nanoTime() 在大约 300 年后溢出...... :-)
  • 啊,很好,我说的是 0ms 到 2500ms 之间:p
  • 我认为这不是问题,但您可以尝试通过将 duration 改为 long 来消除自动装箱吗?
  • duration 可以为 null 如果线程在运行太久后被杀死:/
  • 相反,我使用duration = Long.valueOf(System.nanoTime() - startTime); 来避免自动装箱

标签: java multithreading url duration


【解决方案1】:

所以我拿了你的代码,在末尾添加了一个System.out.println("Time: " + (duration == null ? "aborted" : duration)); 并运行了几千次......它从未返回任何甚至是负面的东西。我什至尝试将连接部分注释掉,最短时间再次接近 120,000ns。

如果您遇到了负面的时间,那么您的代码中的某些内容您没有发布,或者是您的操作系统/JVM 实现的错误。 Java 和 System.nanoTime() 的工作做得非常好。

您对在不同线程中计算时间时的负时差的评论很有趣,但即使发生这种情况,“有点偏离”部分更像是 +/- 10 或 100 ns,绝对不会 >100,000ns。

【讨论】:

  • 我想的是,它不能低于 0ns。现在我切换到ThreadMXBean 来获取CurrentThreadCpuTime 并运行一下。我得到的较低的是0。现在我从一个也使用ThreadPool(通过ExecutorService)的Akka actor 调用这个检查。这意味着我有 10 个线程(我现在定义为 10 个)生成 1 个线程(上面的代码)。也许它太线程化了?
【解决方案2】:

nanoTime 的 javadoc 说

返回的值表示自某个固定但任意的原始时间以来的纳秒(可能在将来,因此值可能为负数)。

所以你需要取开始时间和结束时间之差的绝对值。

【讨论】:

    猜你喜欢
    • 2016-02-23
    • 2016-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-23
    • 2023-03-25
    相关资源
    最近更新 更多