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.