illegalmonitorstateexception - at java lang object wait object java 502
IllegalMonitorStateException en la llamada a wait() (9)
Aquellos que están usando la versión de Java 7.0 o inferior pueden referir el código que usé aquí y funciona.
public class WaitTest {
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
public void waitHere(long waitTime) {
System.out.println("wait started...");
lock.lock();
try {
condition.await(waitTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lock.unlock();
System.out.println("wait ends here...");
}
public static void main(String[] args) {
//Your Code
new WaitTest().waitHere(10);
//Your Code
}
}
Estoy usando multi-threading en java para mi programa. He ejecutado thread con éxito pero cuando estoy usando Thread.wait()
, está lanzando java.lang.IllegalMonitorStateException
. ¿Cómo puedo hacer que un hilo espere hasta que se lo notifiquen?
Como no ha publicado el código, estamos trabajando en la oscuridad. ¿Cuáles son los detalles de la excepción?
¿Estás llamando a Thread.wait () desde el hilo o fuera de él?
Pregunto esto porque según el javadoc para IllegalMonitorStateException, es:
Lanzado para indicar que un subproceso ha intentado esperar en el monitor de un objeto o para notificar a otros subprocesos que esperan en el monitor de un objeto sin poseer el monitor especificado.
Para aclarar esta respuesta, esta llamada a esperar en un hilo también arroja IllegalMonitorStateException, a pesar de ser llamado desde dentro de un bloque sincronizado:
private static final class Lock { }
private final Object lock = new Lock();
@Test
public void testRun() {
ThreadWorker worker = new ThreadWorker();
System.out.println ("Starting worker");
worker.start();
System.out.println ("Worker started - telling it to wait");
try {
synchronized (lock) {
worker.wait();
}
} catch (InterruptedException e1) {
String msg = "InterruptedException: [" + e1.getLocalizedMessage() + "]";
System.out.println (msg);
e1.printStackTrace();
System.out.flush();
}
System.out.println ("Worker done waiting, we''re now waiting for it by joining");
try {
worker.join();
} catch (InterruptedException ex) { }
}
La llamada a Thread.wait () tiene sentido dentro de un código que se sincroniza en el objeto Thread.class. No creo que sea lo que querías decir.
Usted pregunta
¿Cómo puedo hacer que un hilo espere hasta que se lo notifiquen?
Puede hacer que solo su hilo actual espere. Cualquier otro hilo se puede pedir suavemente que espere, si está de acuerdo.
Si desea esperar alguna condición, necesita un objeto de bloqueo: el objeto Thread.class es una opción muy mala: es un AFAIK singleton, por lo que sincronizarlo (excepto para los métodos estáticos de subprocesos) es peligroso.
Los detalles para la sincronización y la espera ya han sido explicados por Tom Hawtin. java.lang.IllegalMonitorStateException
significa que intenta esperar en un objeto en el que no está sincronizado; es ilegal hacerlo.
No estoy seguro de si esto ayudará a alguien más o no, pero esta fue la parte clave para solucionar mi problema en la respuesta del usuario "Tom Hawtin - tacklin":
synchronized (lock) {
makeWakeupNeeded();
lock.notifyAll();
}
Solo el hecho de que el "bloqueo" se pasa como un argumento en synchronized () y también se usa en "lock" .notifyAll ();
Una vez que lo hice en esos 2 lugares lo conseguí trabajando
Recibí una IllegalMonitorStateException
mientras trataba de IllegalMonitorStateException
un hilo en / desde una class
/ hilo diferente. En java 8
puede usar las funciones de lock
de la nueva API de simultaneidad en lugar de funciones synchronized
.
Ya estaba almacenando objetos para transacciones websocket asynchronous
en un WeakHashMap
. La solución en mi caso era también almacenar un objeto de lock
en un ConcurrentHashMap
para respuestas synchronous
. Tenga en cuenta la condition.await
. .wait
(no .wait
).
Para manejar el multi threading utilicé un Executors.newCachedThreadPool()
para crear un grupo de subprocesos .
Sé que este hilo tiene casi 2 años, pero aún necesito cerrar esto ya que también vine a esta sesión de Q / A con el mismo problema ...
Lea esta definición de illegalMonitorException una y otra vez ...
IllegalMonitorException se emite para indicar que un subproceso ha intentado esperar en el monitor de un objeto o para notificar a otros subprocesos que esperan en el monitor de un objeto sin poseer el monitor especificado.
Esta línea dice una y otra vez, IllegalMonitorException viene cuando ocurre una de las 2 situaciones ...
1> espera en el monitor de un objeto sin tener el monitor especificado.
2> notifique a otros subprocesos que esperan en el monitor de un objeto sin ser propietarios del monitor especificado.
Algunos podrían haber obtenido sus respuestas ... que no todos, entonces verifiquen 2 declaraciones ...
sincronizado (objeto)
object.wait ()
Si ambos objetos son iguales ... entonces no puede venir la excepción IlMonitorException.
Ahora lee de nuevo la definición de IllegalMonitorException y no la olvidarás de nuevo ...
Según sus comentarios, parece que está haciendo algo como esto:
Thread thread = new Thread(new Runnable(){
public void run() { // do stuff }});
thread.start();
...
thread.wait();
Hay dos problemas En primer lugar, como han dicho otros, obj.wait()
solo puede obj.wait()
si el hilo actual contiene el mutex primitivo para obj
. Si el hilo actual no contiene el mutex, obtienes la excepción que estás viendo.
El segundo (más importante) problema es que thread.wait()
no hace lo que parece que esperas que haga. Específicamente, thread.wait()
no hace que el subproceso designado espere. Más bien hace que el hilo actual espere hasta que otro hilo llame a thread.notify()
o thread.notifyAll()
.
En realidad, no hay una forma segura de forzar a una instancia de subproceso a pausar si no desea hacerlo. (Lo más cercano que tiene Java a esto es el método de Thread.suspend()
desuso, pero ese método es inherentemente inseguro, como se explica en el Javadoc).
Si desea que el subproceso recién iniciado se detenga, la mejor manera de hacerlo es crear una instancia de CountdownLatch y hacer que la llamada de subproceso await()
en el pestillo se pause. El hilo principal llamaría a countDown()
en el pestillo para permitir que el hilo pausado continúe.
Object.wait()
estar en un bloque synchronized
para que Object.wait()
funcione.
Además, recomiendo consultar los paquetes de simultaneidad en lugar de los paquetes de subprocesamiento de la vieja escuela. Son más seguros y más fáciles de trabajar .
Feliz codificación.
EDITAR
Supuse que se refería a Object.wait()
ya que su excepción es lo que sucede cuando intenta obtener acceso sin mantener el bloqueo de objetos.
wait
se define en Object
, y no en Thread
. El monitor en el Thread
es un poco impredecible.
Aunque todos los objetos Java tienen monitores, generalmente es mejor tener un bloqueo dedicado:
private final Object lock = new Object();
Puede obtener diagnósticos ligeramente más fáciles de leer, a un costo de memoria pequeño (aproximadamente 2 K por proceso) utilizando una clase con nombre:
private static final class Lock { }
private final Object lock = new Lock();
Para wait
o notify
/ notify
notifyAll
un objeto, debe mantener presionado el candado con la instrucción synchronized
. Además, necesitará un ciclo while para verificar la condición de activación (busque un buen texto en el subproceso para explicar por qué).
synchronized (lock) {
while (!isWakeupNeeded()) {
lock.wait();
}
}
Notificar:
synchronized (lock) {
makeWakeupNeeded();
lock.notifyAll();
}
Vale la pena comprender tanto el lenguaje Java como los bloqueos java.util.concurrent.locks
(y java.util.concurrent.atomic
) al acceder a subprocesos múltiples. Pero use estructuras de datos java.util.concurrent
siempre que pueda.