Je sais Thread.sleep () peut faire suspendre un thread Java pendant un certain temps, comme certaines millisecondes et certaines nanosecondes. Mais le problème est l'invocation de cette fonction également entraîne des frais généraux.
Par exemple, si je veux suspendre un thread pendant 100 nanosecondes, et j'appelle Thread.sleep (0, 100). Le coût total de ce processus est invocation_cost + 100 nanosceonds, ce qui peut être beaucoup plus élevé que ce que je veux. Comment pourrais-je éviter ce problème et atteindre mon objectif?
La raison pour laquelle j'ai besoin de cela est que je veux faire une simulation hors ligne. J'ai profilé le temps d'exécution d'une tâche; Maintenant, je veux simuler ce temps d'exécution en suspendant un thread dans la même période.
Merci!
La granularité des mises en veille est généralement liée à la période d'interruption du planificateur de threads. Sous Linux, cette période d'interruption est généralement de 1 ms dans les noyaux récents. Sous Windows, la période d'interruption du planificateur est normalement d'environ 10 ou 15 millisecondes
Si je dois interrompre les discussions pendant des périodes inférieures à cela, j'utilise normalement une attente occupée
MODIFIER : Je suppose que vous obtiendrez les meilleurs résultats sur jrockit + solaris. Les chiffres sur une boîte Windows sont terribles.
@Test
public void testWait(){
final long INTERVAL = 100;
long start = System.nanoTime();
long end=0;
do{
end = System.nanoTime();
}while(start + INTERVAL >= end);
System.out.println(end - start);
}
Pour la simulation, je n'essaierais pas de simuler en temps réel car cela ne vous donne pas de résultats reproductibles. c'est-à-dire que vous ne pouvez pas tester votre simulation.
Au lieu de cela, j'utiliserais une horloge simulée basée sur les données et exécuterais tout aussi vite que possible. Cela vous donne des résultats reproductibles et vous permet de simuler plus rapidement qu'en temps réel (par exemple 2x à 100x plus rapide)
La détection d'un fil prend environ 10 micro-secondes. Il ne sert à rien d'essayer de suspendre un thread pour moins de temps que cela.
Pour attendre occupé pendant une courte période de temps, vous pouvez essayer.
long start = System.nanotime();
while(start + delay >= System.nanoTime());
Remarque: comme @EugeneBeresovsky commente, après que votre machine ait fonctionné pendant 292 ans, cela pourrait déborder, vous pouvez donc choisir d'écrire ceci comme
while(System.nanoTime() - start < delay);
Au lieu de cela, ce sera bien pour les retards de moins de 292 ans. Vous pouvez utiliser System.currentTimeMillis () pour des délais beaucoup plus longs.
Cependant, même cela n'est pas fiable car System.nanoTime () peut prendre jusqu'à 300 ns sur Centos 5.x, donc l'appeler deux fois va prendre beaucoup plus de temps que 100 ns. De nombreux systèmes d'exploitation ont également une résolution de 1000 ns (1 micro-seconde), de sorte que cette boucle attendra jusqu'à 1 micro-seconde quel que soit le retard que vous recherchez.
Au lieu de cela, ce que vous pouvez faire est d'attendre occupé dans une courte boucle qui n'est pas optimisée.
Pour un retard de 100 ns, je pense qu'il serait préférable d'attendre occupé ce que vous attendez au lieu de créer une boucle occupée distincte.
public static void busySleep(long nanos)
{
long elapsed;
final long startTime = System.nanoTime();
do {
elapsed = System.nanoTime() - startTime;
} while (elapsed < nanos);
}
Un autre problème avec Thread.sleep()
est qu'il n'est pas garanti de se réveiller après l'heure spécifiée. Un fil endormi est garanti pour dormir pendant les nano/micro secondes spécifiées, mais pas garanti pour se réveiller immédiatement après cela. Puisque vous parlez des intervalles de nanosecondes, vous voudrez peut-être essayer Object.wait(long, int)
.
J'ai été assez cohérent avec l'ordre de 10 secondes de nanosecondes avec la méthode ci-dessus.
Faites une attente occupée (c.-à-d. Que vous ayez une boucle while à travers tant de numéros sans rien faire). Au début de votre programme, vous pouvez chronométrer le temps qu'il a fallu pour exécuter cette attente occupée et l'augmenter ou la diminuer pour arriver à 5 nano secondes
J'ai trouvé un objet. L'attente devient poilue avec cette fréquence. Notez également qu'une solution d'attente occupée dépendra probablement de la machine.