thread que problem para library java multithreading sleep

java - que - thread.sleep() c#



Dormir y comprobar hasta que la condiciĆ³n sea verdadera. (6)

Deberías estar usando una Condition .

Si desea tener un tiempo de espera adicional a la condición, consulte await(long time, TimeUnit unit)

¿Hay alguna biblioteca en Java que haga lo siguiente? Un thread debe estar repetidamente sleep durante x milisegundos hasta que una condición se vuelva verdadera o se alcance el tiempo máximo.

Esta situación ocurre principalmente cuando una prueba espera que se cumpla alguna condición. La condición está influenciada por otro thread .

[EDITAR] Solo para que quede más claro, quiero que la prueba espere solo X ms antes de que falle. No puede esperar para siempre que una condición se haga realidad. Estoy agregando un ejemplo artificial.

class StateHolder{ boolean active = false; StateHolder(){ new Thread(new Runnable(){ public void run(){ active = true; } }, "State-Changer").start() } boolean isActive(){ return active; } } class StateHolderTest{ @Test public void shouldTurnActive(){ StateHolder holder = new StateHolder(); assertTrue(holder.isActive); // i want this call not to fail } }


Estaba buscando una solución como la que proporciona la aguardilidad. Creo que elegí un ejemplo incorrecto en mi pregunta. Lo que quise decir fue en una situación en la que está esperando que ocurra un evento asíncrono creado por un servicio de terceros y el cliente no puede modificar el servicio para ofrecer notificaciones. Un ejemplo más razonable sería el siguiente.

class ThirdPartyService { ThirdPartyService() { new Thread() { public void run() { ServerSocket serverSocket = new ServerSocket(300); Socket socket = serverSocket.accept(); // ... handle socket ... } }.start(); } } class ThirdPartyTest { @Before public void startThirdPartyService() { new ThirdPartyService(); } @Test public void assertThirdPartyServiceBecomesAvailableForService() { Client client = new Client(); Awaitility.await().atMost(50, SECONDS).untilCall(to(client).canConnectTo(300), equalTo(true)); } } class Client { public boolean canConnect(int port) { try { Socket socket = new Socket(port); return true; } catch (Exception e) { return false; } } }


No debes dormir y comprobar y dormir y comprobar. Desea esperar en una variable de condición y cambiar la condición y reactivar el hilo cuando sea el momento de hacer algo.


Parece que lo que desea hacer es verificar la condición y luego, si es falso, espere hasta que se agote el tiempo. Luego, en el otro subproceso, notifique Todo una vez que se complete la operación.

Camarero

synchronized(sharedObject){ if(conditionIsFalse){ sharedObject.wait(timeout); if(conditionIsFalse){ //check if this was woken up by a notify or something else //report some error } else{ //do stuff when true } } else{ //do stuff when true } }

Cambiador

synchronized(sharedObject){ //do stuff to change the condition sharedObject.notifyAll(); }

Eso debería hacer el truco por ti. También puede hacerlo utilizando un bloqueo de giro, pero debería verificar el tiempo de espera cada vez que pase por el bucle. Sin embargo, el código podría ser un poco más simple.


Awaitility ofrece una solución simple y limpia:

await (). atMost (10, SECONDS) .until (() -> condition ());


EDITAR

La mayoría de las respuestas se centran en la API de bajo nivel con esperas y notificaciones o Condiciones (que funcionan más o menos de la misma manera): es difícil acertar cuando no estás acostumbrado. Prueba: 2 de estas respuestas no usan esperar correctamente.
java.util.concurrent ofrece una API de alto nivel donde se han ocultado todas esas complejidades.

En mi humilde opinión, no tiene sentido usar un patrón de espera / notificación cuando hay una clase incorporada en el paquete concurrente que logra lo mismo.

Un CountDownLatch con un conteo inicial de 1 hace exactamente eso:

  • Cuando la condición se vuelva verdadera, llame a latch.countdown();
  • en su hilo de espera, use: boolean ok = latch.await(1, TimeUnit.SECONDS);

Ejemplo elaborado:

final CountDownLatch done = new CountDownLatch(1); new Thread(new Runnable() { @Override public void run() { longProcessing(); done.countDown(); } }).start(); //in your waiting thread: boolean processingCompleteWithin1Second = done.await(1, TimeUnit.SECONDS);

Nota: CountDownLatches son seguros para subprocesos.