2017-07-31 2 views
6

Comme this question, Thread.sleep n'est pas forcément garanti pour dormir pendant la durée que vous spécifiez: il peut être plus court ou plus long.Comment puis-je garantir que Thread.sleep dort pendant au moins ce laps de temps?

Si vous lisez la documentation pour Thread.sleep, vous verrez qu'il n'y a pas de garanties solides sur la durée exacte qui sera dormie. Il précise notamment la durée est

sous réserve de la précision et l'exactitude des compteurs du système et ordonnanceurs

qui est (intentionnellement) vague mais laisse entendre que la durée ne doit pas être invoquée trop lourdement.

La granularité des durées de sommeil possibles sur un système d'exploitation particulier est déterminée par la période d'interruption du planificateur de threads.

Dans Windows, période d'interruption du programmateur est normalement environ 10 ou 15 millisecondes (qui je crois est dictée par le processeur), mais une période plus peut être demandé dans le logiciel et la machine virtuelle Java Hotspot le fait quand il le juge nécessaire

Source, Souligné par

Comment puis-je garantir que pratiquement toute la durée du sommeil sera au moins la valeur que je spécifie?

+0

Quel est votre cas d'utilisation pour rendre le sommeil de fil x temps? Êtes-vous juste la planification? Si oui, il existe de meilleures façons de le faire – UserF40

+3

@ UserF40 une application que j'avais à l'esprit est de limiter les demandes (ou d'autres types d'événements) à dire, un maximum de N événements par seconde. Si vous êtes sur le point de faire la Nième demande et que la première demande a été faite il y a moins d'une seconde, vous devez attendre * au moins * le temps requis avant de faire la demande. –

+0

@ UserF40 Je n'ai pas personnellement de cas d'utilisation (si vous regardez les commentaires de la question liée, vous verrez pourquoi j'ai posé la question;)) mais ce que Klitos a mentionné semble raisonnable. – Michael

Répondre

4

La meilleure solution pratique consiste à temps le sommeil et continuer à dormir pendant qu'il est temps restant:

public void sleepAtLeast(long millis) throws InterruptedException 
{ 
    long t0 = System.currentTimeMillis(); 
    long millisLeft = millis; 
    while (millisLeft > 0) { 
     Thread.sleep(millisLeft); 
     long t1 = System.currentTimeMillis(); 
     millisLeft = millis - (t1 - t0); 
    } 
} 

Code et information est de here

+1

Bonne solution mais je déconseille d'utiliser 'currentTimeMillis'. Si l'utilisateur ajuste l'heure du système (ou si vous utilisez un service NTP) pendant que votre application Java est en cours d'exécution, cette méthode se comportera de manière incorrecte. Utilisez 'System.nanoTime()' à la place. –