Java Thread.sleep()花费的时间比预期的长?

Java Thread.sleep()花费的时间比预期的长?,java,multithreading,rmi,sleep,Java,Multithreading,Rmi,Sleep,我们有一个使用持久性框架的Java客户机/服务器RMI应用程序。启动客户端会话后,我们将启动以下线程: Thread checkInThread = new Thread() { public void run() { while(true) { try { getServer().checkIn(userId); } catch(Exception ex) { JOptionPane.

我们有一个使用持久性框架的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秒的间隔定期发生(假设它们是客户端和服务器之间的连接)

getServer().checkIn(userId)

因此,getServer或checkIn函数可能需要15秒以上的时间才能返回

线程将在45秒以上的时间内出去吃午饭


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


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

您绝对不能这样做。RMI中没有连接这样的东西,因此您正在测试一个不存在的条件。您还干扰了RMI的连接池。正确的方法是通过和
Unreferenced
接口完成您正在尝试的操作。RMI已经可以在客户端失去连接时告诉您,而无需所有这些开销。”仍然连接“在RMI中没有意义”

可能是睡眠前的部分被阻塞了,例如,对话框被显示并等待用户交互?我想知道日志记录在这里是否有帮助。顺便说一句,我希望空的catch块只是为了简单的原因而存在,实际上不是空的。正如@HovercraftFullOfEels所说的,log。具体地说,记录线程调用
sleep
的时间和
sleep
返回的时间。这将决定延迟是在
睡眠中,还是更可能是在其他地方。我不同意重复。另一个问题的答案是,在非实时JVM和操作系统上,睡眠时间可能比给定的毫秒数要长。但是,晚了45秒或更多?我想这里还有别的事情。如果没有更多的信息,就说不出什么——这个例子没有显示时间是如何测量的——但是Huy Nguyen Ngoc的答案似乎是合理的:OP可能错误地将花费在
getServer()中的时间归为checkIn(userId)操作。该方法所做的只是更新服务器上包含的HashMap<代码>userCheckInMap.put(userId,newtime())您确定它没有任何网络活动吗?那么为什么要捕获JOptionPane.showMessageDialog(parentFrame,“与服务器的连接丢失”);getServer可能是问题所在,而不是签入功能顺便说一句,这不是一个重复的问题。Threed.sleep在毫秒级上并不准确,因为它取决于线程优先级和实现细节,如计时器分辨率,但决不能从15秒跳到45秒以上。是的@Huy Nguyen Ngoc,谢谢你。我只是看了一下线程,它并不是一个真正需要实时性的问题。我们不关心毫秒,但希望线程在45秒内至少执行一次。如果服务器不可用,建立连接将在毫秒内失败,如果服务器不可用,它如何检测超时?