Estoy haciendo una aplicación Java con un hilo de lógica de aplicación y un hilo de acceso a la base de datos. Ambos persisten durante toda la vida útil de la aplicación y ambos deben ejecutarse al mismo tiempo (uno habla con el servidor, uno habla con el usuario; cuando la aplicación se inicia por completo, necesito que ambos funcionen).
Sin embargo, en el inicio, necesito asegurarme de que inicialmente el subproceso de la aplicación espere hasta que el subproceso db esté listo (actualmente determinado mediante una encuesta de un método personalizado dbthread.isReady()
). No me importaría si el hilo de la aplicación se bloquea hasta que el hilo de db esté listo.
Thread.join()
no parece una solución: el subproceso db solo se cierra al cerrar la aplicación.
while (!dbthread.isReady()) {}
funciona, pero el bucle vacío consume muchos ciclos de procesador.
¿Alguna otra idea? Gracias.
fuente
a
está esperando en el objeto,synchronised(object)
¿cómo puede pasar otro hilosynchronized(object)
para llamar alobject.notifyAll()
? En mi programa, todo se atascó ensynchronozed
bloques.object.wait()
efectivamente desbloqueando el bloqueo en ese objeto. Cuando el segundo subproceso "sale" de su bloque sincronizado, los otros objetos se liberan delwait
método y vuelven a obtener el bloqueo en ese punto.Use un CountDownLatch con un contador de 1.
Ahora en el hilo de la aplicación do-
En el hilo db, después de que haya terminado, haga:
fuente
countDown()
en unfinally{}
bloqueRequisito ::
Responder ::
¡¡Trabajo hecho!! Ver ejemplo a continuación
Salida de este programa ::
Puede ver que tarda 6 segundos antes de terminar su tarea, que es mayor que otro hilo. Así que Future.get () espera hasta que se complete la tarea.
Si no usa future.get () no espera para terminar y ejecuta el consumo de tiempo basado.
Buena suerte con la concurrencia de Java.
fuente
CountdownLatch
es, pero el tuyo es un enfoque mucho más flexible.Muchas respuestas correctas pero sin un ejemplo simple. Aquí hay una manera fácil y simple de usar
CountDownLatch
:fuente
Use esta clase como esta entonces:
Crea un ThreadEvent:
En el método esto está esperando resultados:
Y en el método que está creando los resultados después de haber creado todos los resultados:
EDITAR:
(Perdón por editar esta publicación, pero este código tiene una condición de carrera muy mala y no tengo suficiente reputación para comentar)
Solo puede usar esto si está 100% seguro de que se llama a signal () después de wait (). Esta es la gran razón por la que no puede utilizar objetos Java como, por ejemplo, Windows Events.
Si el código se ejecuta en este orden:
entonces el hilo 2 esperará para siempre . Esto se debe a que Object.notify () solo activa uno de los subprocesos actualmente en ejecución. Un hilo que espera más tarde no se despierta. Esto es muy diferente de cómo espero que funcionen los eventos, donde se señala un evento hasta que a) espere ob) restablezca explícitamente.
Nota: La mayoría de las veces, debe usar notifyAll (), pero esto no es relevante para el problema de "esperar para siempre" anterior.
fuente
Pruebe la clase CountDownLatch fuera del
java.util.concurrent
paquete, que proporciona mecanismos de sincronización de mayor nivel, que son mucho menos propensos a errores que cualquiera de las cosas de bajo nivel.fuente
Puede hacerlo utilizando un objeto Intercambiador compartido entre los dos hilos:
Y en el segundo hilo:
Como han dicho otros, no tome este código alegre y solo copie y pegue. Lee un poco primero.
fuente
La interfaz Future del
java.lang.concurrent
paquete está diseñada para proporcionar acceso a los resultados calculados en otro hilo.Eche un vistazo a FutureTask y ExecutorService para obtener una forma lista de hacer este tipo de cosas.
Recomiendo leer Java Concurrency In Practice a cualquier persona interesada en la concurrencia y el subprocesamiento múltiple. Obviamente se concentra en Java, pero también hay mucha carne para cualquiera que trabaje en otros idiomas.
fuente
Si desea algo rápido y sucio, puede agregar una llamada Thread.sleep () dentro de su ciclo while. Si la biblioteca de la base de datos es algo que no puede cambiar, entonces realmente no hay otra solución fácil. El sondeo de la base de datos hasta que esté listo con un período de espera no matará el rendimiento.
Difícilmente algo que se pueda llamar código elegante, pero hace el trabajo.
En caso de que pueda modificar el código de la base de datos, es mejor usar un mutex como se propone en otras respuestas.
fuente
Esto se aplica a todos los idiomas:
Desea tener un modelo de evento / oyente. Crea un oyente para esperar un evento en particular. El evento se crearía (o se señalaría) en su hilo de trabajo. Esto bloqueará el hilo hasta que se reciba la señal en lugar de sondear constantemente para ver si se cumple una condición, como la solución que tiene actualmente.
Su situación es una de las causas más comunes de puntos muertos: asegúrese de señalar el otro hilo independientemente de los errores que puedan haber ocurrido. Ejemplo, si su aplicación arroja una excepción, y nunca llama al método para indicarle al otro que las cosas se han completado. Esto hará que el otro hilo nunca 'se despierte'.
Le sugiero que examine los conceptos de uso de eventos y controladores de eventos para comprender mejor este paradigma antes de implementar su caso.
Alternativamente, puede usar una llamada de función de bloqueo usando un mutex, lo que hará que el hilo espere a que el recurso esté libre. Para hacer esto, necesita una buena sincronización de hilos, como:
fuente
Puede leer desde una cola de bloqueo en un hilo y escribir en otro hilo.
fuente
Ya que
join()
ha sido descartadoPuedes considerar otras alternativas:
invokeAll from
ExecutorService
ForkJoinPool o newWorkStealingPool de
Executors
(desde el lanzamiento de Java 8)fuente
Esta idea puede aplicarse ?. Si usa CountdownLatches o Semaphores funciona perfecto, pero si está buscando la respuesta más fácil para una entrevista, creo que esto puede aplicarse.
fuente