Java 睡得很奇怪

Java 睡得很奇怪,java,multithreading,concurrency,thread-sleep,Java,Multithreading,Concurrency,Thread Sleep,我有以下代码: public Move chooseMove(Board board) { // start parallel thread this.tn = new TreeNode(this.myboard, this, null); tn.stop = false; this.curT = (new Thread(tn)); this.curT.start(); try { long startTime = Syste

我有以下代码:

public Move chooseMove(Board board) {

    // start parallel thread
    this.tn = new TreeNode(this.myboard, this, null);
    tn.stop = false;
    this.curT = (new Thread(tn));
    this.curT.start();


    try {
        long startTime = System.currentTimeMillis();
        Thread.sleep(4000 );
        System.out.println(System.currentTimeMillis() - startTime);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        tn.stop=true;
        return getBestMove();
    }
}
输出有时是一个远大于4000ms的值,比如5400ms,这意味着线程的睡眠时间超过了它应该睡眠的时间。有什么帮助吗? 谢谢

编辑: 我知道不能保证线程在指定的延迟之后完全停止睡眠。然而,额外的1400ms是一个很长的延迟。基本上,我正在实现一个游戏玩家代理,我需要一种方法来运行一个任务,然后在5s后向服务器返回一个值(或者服务器结束游戏)。服务器正在使用java.util.Timer.schedule(TimerTask任务,长延迟)。在上面的代码中,只有一个线程与主线程并行运行,即this.curT,因此没有太多的多线程。

来自:

提供了两种重载版本的睡眠:一种将睡眠时间指定为毫秒,另一种将睡眠时间指定为纳秒。但是,这些睡眠时间不能保证精确,因为它们受到底层操作系统提供的功能的限制。此外,睡眠时间可以通过中断来终止,我们将在后面的部分中看到。在任何情况下,您都不能假设调用sleep将在指定的时间段内暂停线程

发件人:

提供了两种重载版本的睡眠:一种将睡眠时间指定为毫秒,另一种将睡眠时间指定为纳秒。但是,这些睡眠时间不能保证精确,因为它们受到底层操作系统提供的功能的限制。此外,睡眠时间可以通过中断来终止,我们将在后面的部分中看到。在任何情况下,您都不能假设调用sleep将在指定的时间段内暂停线程


这是常见的行为,在javadoc中有描述:

使当前执行的线程休眠(暂时停止执行)指定的毫秒数,取决于系统计时器和调度程序的精度和准确性


基于此,不能保证
线程#睡眠
以参数中规定的毫秒数停止线程的工作。

这是常见的行为,在javadoc中有描述:

使当前执行的线程休眠(暂时停止执行)指定的毫秒数,取决于系统计时器和调度程序的精度和准确性

基于此,无法保证
Thread#sleep
以参数中规定的毫秒数停止线程的工作。

Thread#sleep
将使线程精确地睡眠4秒,然后醒来。
一旦你的线程被唤醒,操作系统调度程序就会将其放入可运行队列中。
当调度程序下次选择它时,它将成为一个正在运行的线程,即将占用CPU。
因此,由于操作系统调度程序会增加额外的延迟开销,这可能会因操作系统、系统负载等而异。这与
Java
Thread无关。sleep
将使线程精确地睡眠4秒钟,然后醒来。
一旦你的线程被唤醒,操作系统调度程序就会将其放入可运行队列中。
当调度程序下次选择它时,它将成为一个正在运行的线程,即将占用CPU。

因此,由于操作系统调度程序,会产生额外的延迟开销,这可能会因操作系统、系统负载等而异。这与
Java

无关。处理器是否正忙于做其他事情?如果处理器真的处于颠簸状态,并且有大量并发线程活动,那么一个线程在一段时间内无法获得周期。您多久会获得一次这种行为?尝试在不使用任何其他代码的情况下,仅使用睡眠调用运行线程。如果我在单个线程中单独运行thread.sleep,则它的行为正确。但是我的真实代码中只有两个线程在运行,如上图所示,处理器是否忙于做其他事情?如果处理器真的处于颠簸状态,并且有大量并发线程活动,那么一个线程在一段时间内无法获得周期。您多久会获得一次这种行为?尝试在不使用任何其他代码的情况下,仅使用睡眠调用运行线程。如果我在单个线程中单独运行thread.sleep,则它的行为正确。但我的真实代码中只有两个线程在运行,如上图所示是的,但根据我的经验,它是@Vito。任何关于它为什么要等待额外的1400ms的解释?1400ms是一段很长的时间,但垃圾收集之类的活动可以解释这一点。不过,底线是Thread.sleep中的暂停时间不能依赖于准确。是的,但根据我的经验,它确实是@Vito。任何关于它为什么要等待额外的1400ms的解释?1400ms是一段很长的时间,但垃圾收集之类的活动可以解释这一点。但底线是,Thread.sleep中的暂停时间不可能精确。有没有办法通过影响操作系统计划程序可运行队列优先级使线程在4秒后运行?您可以分配
MAX_PRIORITY
,但仍然不能保证达到您期望的精确级别。如果需要您应该在4秒钟内进行轮询,而不是
sleep
。使用
sleep
时,您放弃了CPU,并且无法保证在4秒钟内将其恢复。可以保证你的线程会在4秒钟内唤醒,但是没有别的。你说的“轮询”是什么意思?
while(true){if(System.currentTimeMillis()-startTime>4000)break}
我试过了,但是如果检查是在说[System.currentTimeMillis()-startTime=3990]时完成的如果循环中的代码需要很长时间(不应该这样做,但我有多个线程在运行,所以我认为这可能是原因),那么它将超过4000ms。有没有办法