thread entre diferencias crear java sleep thread-sleep method-invocation nanotime

entre - ¿Cómo suspender un subproceso de Java por un pequeño período de tiempo, como 100 nanosegundos?



thread.sleep java (5)

Sé que Thread.sleep () puede hacer que un hilo de Java se suspenda por un tiempo, como ciertos milisegundos y ciertos nanosegundos. Pero el problema es que la invocación de esta función también provoca sobrecarga.

Por ejemplo, si quiero que un hilo se suspenda por 100 nanosegundos, y llamo Thread.sleep (0, 100) . El costo total de este proceso es invocation_cost + 100 nanosceonds , que puede ser mucho mayor de lo que quiero. ¿Cómo podría evitar este problema y lograr mi propósito?

La razón por la que necesito esto es que quiero hacer una simulación fuera de línea. Perfila el tiempo de ejecución de una tarea; Ahora quiero simular este tiempo de ejecución suspendiendo un hilo en el mismo período de tiempo.

¡Gracias!


Haga una espera ocupada, (es decir, haga un ciclo de bucle while a través de tantos números sin hacer nada). Al inicio de su programa, puede cronometrar la cantidad de tiempo que le tomó ejecutar esta espera ocupada y aumentarla o disminuirla para llegar a 5 nano segundos

Descubrí que object.wait se vuelve peliaguda con esta frecuencia. También tenga en cuenta que una solución de espera ocupada es muy probable que dependa de la máquina. Por eso debería tener un paso de calibración al inicio de su programa.


La granularidad de los tiempos de espera generalmente está limitada por el período de interrupción del programador de hilos. En Linux, este período de interrupción es generalmente de 1 ms en los núcleos recientes. En Windows, el período de interrupción del programador es normalmente de unos 10 o 15 milisegundos.

Si tengo que detener los subprocesos por períodos inferiores a este, normalmente uso una espera ocupada

EDITAR : Sospecho que obtendrá mejores resultados en jrockit + solaris. Los números en una caja de ventanas son 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); }


Para la simulación, no intentaría simular en tiempo real, ya que esto no ofrece resultados reproducibles. es decir, no puedes probar tu simulación.

En su lugar, usaría un reloj simulado basado en datos y ejecutaría todo lo más rápido posible. Esto le brinda resultados reproducibles y le permite simular más rápido que en tiempo real (por ejemplo, 2x a 100x más rápido)

Sospechar un hilo lleva alrededor de 10 microsegundos. No tiene sentido intentar suspender un hilo por menos tiempo que esto.

Para esperar ocupado por un corto período de tiempo puede intentar.

long start = System.nanotime(); while(start + delay >= System.nanoTime());

Nota: como comenta @EugeneBeresovsky, después de que su máquina haya estado funcionando durante 292 años, esto podría desbordarse, por lo que puede elegir escribir esto como

while(System.nanoTime() - start < delay);

Esto multará por retrasos de menos de 292 años. Puede usar System.currentTimeMillis () para demoras mucho más largas.

Sin embargo, incluso esto no es confiable, ya que System.nanoTime () puede tardar hasta 300 ns en Centos 5.x, por lo que llamarlo dos veces llevará más tiempo que 100 ns. Además, muchos sistemas operativos solo tienen una resolución de 1000 ns (1 microsegundo), por lo que este bucle esperará hasta 1 microsegundo independientemente del retraso que esté buscando.

En su lugar, lo que puede hacer es esperar ocupado en un bucle corto que no está optimizado.

Para un retraso de 100 ns, sospecho que sería mejor esperar ocupado en lo que esté esperando en lugar de crear un ciclo de ocupado separado.


Un problema más con Thread.sleep() es que no se garantiza que se active después del tiempo especificado. Un hilo para dormir está garantizado para dormir durante los nano / microsegundos especificados, pero no se garantiza que se despierte inmediatamente después de eso. Ya que estás hablando a intervalos de nanosegundos, es posible que desees probar Object.wait(long, int) .

He sido bastante consistente con el orden de 10s de nanosegundos con el método anterior.


public static void busySleep(long nanos) { long elapsed; final long startTime = System.nanoTime(); do { elapsed = System.nanoTime() - startTime; } while (elapsed < nanos); }