【问题标题】:Thread.sleep() taking longer than expected?Thread.sleep() 花费的时间比预期的要长?
【发布时间】:2016-05-22 13:15:34
【问题描述】:

我们有一个使用持久性框架的 Java 客户端/服务器 RMI 应用程序。在启动客户端会话时,我们启动以下线程:

 Thread checkInThread = new Thread() {
    public void run() {
      while(true) {
        try {
          getServer().checkIn(userId);
        }
        catch(Exception ex) {
          JOptionPane.showMessageDialog(parentFrame, "The connection to the server was lost.");
          ex.printStackTrace();
        }
        try {
          Thread.sleep(15000);
        }
        catch(InterruptedException e) {
        }
      }
    }
  };

这用于跟踪客户端会话是否失去与服务器的连接。如果客户端在 45 秒内没有签入,那么我们需要从该客户端的会话中清理许多事情。在他们超过 45 秒阈值后下一次签入时,我们从系统引导他们,然后允许他们重新登录。理论上,唯一应该发生的情况是客户端 PC 失去与服务器的连接。

但是,我们遇到过线程运行良好并且每 15 秒检查一次的情况,然后由于未知原因,线程将只出去吃午饭超过 45 秒。最终客户端将重新签入,但在此期间似乎有什么东西阻止了线程的执行。我们在客户端使用 Swing 和 JavaFX 都体验过这一点。客户端/服务器仅与 Windows 操作系统兼容。

是否有一种简单的方法可以找出导致这种情况发生的原因,或者是否有更好的方法来确保以 15 秒的间隔定期进行签入(假设它们是客户端和服务器之间的连接)?

【问题讨论】:

  • 可能是睡眠前的部分阻塞,例如对话框已显示并等待用户交互?
  • 我想知道日志记录是否会有所帮助。
  • 顺便说一句,我希望空的 catch 块只是为了简单起见,而不是在现实中为空。
  • 正如@HovercraftFullOfEels 所说,记录。具体来说,记录线程调用sleep 的时间和sleep 返回的时间。这将确定延迟是在sleep,还是更有可能在其他地方。
  • 我不同意这个副本。另一个问题的答案说,在非实时 JVM 和操作系统上,睡眠时间可能会超过给定的毫秒数。但是,迟到了 45 秒或更长时间?我认为这里正在发生其他事情。不能说没有更多信息——这个例子没有显示时间是如何测量的——但是 Huy Nguyen Ngoc 的回答似乎是合理的: OP 可能错误地将在getServer().checkIn(userId); 中花费的时间归因于 sleep()打电话。

标签: java multithreading rmi sleep


【解决方案1】:

getServer().checkIn(userId);

getServer 或 checkIn 函数可能需要超过 15 秒才能返回,因此

线程只会出去吃午饭超过 45 秒。

【讨论】:

  • 该方法所做的只是更新服务器上包含的 HashMap。 userCheckInMap.put(userId, new Time());
  • 您确定它没有任何网络活动吗?那你为什么抓到 JOptionPane.showMessageDialog(parentFrame, "The connection to the server was lost."); getServer 可能是问题所在,而不是 checkIn 函数
  • 顺便说一句,这不是与stackoverflow.com/questions/6095712/…的重复问题。 Threed.sleep 在毫秒数量级上并不准确,因为它取决于线程优先级和实现细节(例如计时器分辨率),但它绝不应该从 15 秒跳到 45+ 秒。
  • 是的@Huy Nguyen Ngoc 谢谢你。我只是看了一下线程,这并不是需要它是实时的问题。我们不关心毫秒,但希望线程在 45 秒跨度内至少执行一次。
  • 如果服务器不可用,建立连接会在几毫秒内失败,如果服务器不可用,它是如何检测到超时的?
【解决方案2】:

当客户端机器进入睡眠或休眠模式时,可能会发生这种情况。通常是笔记本电脑刚合上盖子的时候。

也可能会出现持续 >15 秒的临时网络中断,但允许在网络恢复时自动恢复连接。在这种情况下,客户端可能会卡在 .checkIn() 中,而不是 sleep()

【讨论】:

    【解决方案3】:

    您绝对不应该这样做。 RMI 中没有连接之类的东西,ergo 您正在测试一个不存在的条件。您还干扰了 RMI 的连接池。完成您尝试的正确方法是通过remote session patternUnreferenced 接口。 RMI 已经可以告诉您客户端何时失去连接,而无需所有这些开销。 “仍然连接”在 RMI 中没有任何意义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-30
      • 1970-01-01
      • 2020-04-01
      • 1970-01-01
      • 2021-09-18
      相关资源
      最近更新 更多