Tengo un hilo que actualiza su estado de vez en cuando y quiero que un segundo hilo pueda esperar a que se realice el primer hilo. Algo como esto:Esperando un evento en Java: ¿qué tan difícil es?
Thread 1:
while(true) {
...do something...
foo.notifyAll()
...wait for some condition that might never happen...
...
}
Thread 2:
...
foo.wait();
...
Ahora bien, esto se ve bien y todo a menos de rosca de 1 notifyAll() se ejecuta antes de espera de rosca de 2(), en la cual Tema caso 2 espera hasta Tema 1 notifica nuevo (que nunca podría suceder) .
Mis posibles soluciones:
a) que podría utilizar un CountDownLatch o un futuro, pero ambos tienen el problema de que por sí sólo se ejecutan una vez . Es decir, en el ciclo while de Thread 1, necesitaría crear un nuevo foo para esperar cada vez y el Thread 2 necesitaría preguntar a qué foo esperar. Tengo un mal presentimiento sobre simplemente escribiendo
while(true) {
foo = new FutureTask();
...
foo.set(...);
...wait for a condition that might never be set...
...
}
como me temo que al foo = nueva FutureTask(), lo que sucede cuando alguien esperó a que el viejo foo (por "alguna razón", estableció que no fue llamado, por ejemplo, una error en el manejo de excepciones)?
b) O podría usar un semáforo:
class Event {
Semaphore sem;
Event() { sem = new Semaphore(1); sem . }
void signal() { sem.release(); }
void reset() { sem.acquire(1); }
void wait() { if (sem.tryAcquire(1)) { sem.release(); } }
}
Pero me temo que hay una cierta condición de carrera, si varios subprocesos son wait() ing para ello, mientras que otra señal() s y reset () s.
Pregunta:
¿No hay nada en la API de Java que se asemeja al comportamiento de eventos de Windows? O, si desprecia Windows, algo así como el WaitGroup de Golang (es decir, un CountDownLatch que permite countUp())? ¿Cualquier cosa?
Como hacerlo manualmente:
Tema 2 no se puede esperar simplemente a causa de despertar y espuria en Java no hay manera de saber por qué regresó Object.wait(). Entonces necesito una variable de condición que almacene si el evento está señalado o no. Tema 2:
synchronized(foo) {
while(!condition) {
foo.wait();
}
}
Y hilo 1, por supuesto, establece la condición de verdad en un bloque sincronizado. ¡Gracias a weekens por la pista!
¿Existe una clase existente que ajuste ese comportamiento?
¿Debo copiar y pegar el código?
¿Qué problema en realidad tratando de resolver? Aunque estoy seguro de que este problema se puede resolver, aún así me gustaría preguntar, así sabremos que esta es la solución correcta para su problema. Este tipo de juego con los subprocesos y semáforos, aunque bien entendido, es falsamente propenso a fallas debido a pequeños errores, por lo que podría haber una forma más legible y fácil de entender para hacer lo que desea lograr. En particular, suena como un patrón simple de escucha uniforme donde los oyentes se registran con la fuente de los eventos sería más adecuado. – Thor84no
Sí, un oyente de eventos resolvería el problema dejando que el hilo 1 se actualice. Este suele ser el método preferido, p. en un entorno de servidor. Sin embargo, me encontré con el problema de "extraer" hilo de forma segura para las actualizaciones de vez en cuando y nunca tuve una solución limpia hasta ahora. – Kosta