¿Cómo usar esperar y notificar en Java sin IllegalMonitorStateException?

7 minutos de lectura

Tengo 2 matrices y necesito multiplicarlas y luego imprimir los resultados de cada celda. Tan pronto como una celda esté lista, necesito imprimirla, pero por ejemplo, necesito imprimir el [0][0] celda antes de celda [2][0] incluso si el resultado de [2][0] está listo primero. Así que necesito imprimirlo por pedido. Así que mi idea es hacer que el hilo de la impresora espere hasta que el multiplyThread le notifica que la celda correcta está lista para ser impresa y luego el printerThread imprimirá la celda y volverá a esperar y así sucesivamente.

Así que tengo este hilo que hace la multiplicación:

public void run() 
{
    int countNumOfActions = 0; // How many multiplications have we done
    int maxActions = randomize(); // Maximum number of actions allowed

    for (int i = 0; i < size; i++)
    {       
        result[rowNum][colNum] = result[rowNum][colNum] + row[i] * col[i];
        countNumOfActions++;
        // Reached the number of allowed actions
        if (countNumOfActions >= maxActions)
        {
            countNumOfActions = 0;
            maxActions = randomize();
            yield();
        }   
    }
    isFinished[rowNum][colNum] = true;
    notify();
}

Hilo que imprime el resultado de cada celda:

public void run()
{
    int j = 0; // Columns counter
    int i = 0; // Rows counter
    System.out.println("The result matrix of the multiplication is:");

    while (i < creator.getmThreads().length)
    {
        synchronized (this)
        {
            try 
            {
                this.wait();
            } 
            catch (InterruptedException e1) 
            {
            }
        }
        if (creator.getmThreads()[i][j].getIsFinished()[i][j] == true)
        {
            if (j < creator.getmThreads()[i].length)
            {
                System.out.print(creator.getResult()[i][j] + " ");
                j++;
            }
            else
            {
                System.out.println();
                j = 0;
                i++;
                System.out.print(creator.getResult()[i][j] + " ");
            }
        }
    }

Ahora me arroja estas excepciones:

Exception in thread "Thread-9" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-6" Exception in thread "Thread-4" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-5" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-8" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-7" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-11" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-10" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-12" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)

línea 49 en multiplyThread es el “notificar ()”.. Creo que necesito usar el sincronizado de manera diferente, pero no estoy seguro de cómo.

Si alguien puede ayudar a que este código funcione, se lo agradeceré mucho.

¿Como usar esperar y notificar en Java sin
bomba

Para poder llamar notificar() necesita sincronizar en el mismo objeto.

synchronized (someObject) {
    someObject.wait();
}

/* different thread / object */
synchronized (someObject) {
    someObject.notify();
}

  • los while(!JobCompleted); La opción generalmente es una mala idea porque ata su CPU al 100% verificando la misma variable constantemente (ver aquí)

    – Matt Lyons

    1 de junio de 2013 a las 21:39

  • while(!JobCompleted) Thread.sleep(5); no tiene ese problema

    – Beni Bela

    25 de diciembre de 2013 a las 18:32

  • Todavía tiene el problema de ser algo completamente diferente. Las encuestas (verificar repetidamente si se cumple alguna condición, es decir, lo que está haciendo) generalmente son menos preferidas que recibir una notificación si dicha condición cambia (es decir, lo que describí en la respuesta).

    – bomba

    27 de diciembre de 2013 a las 7:10

  • @huseyintugrulbuyukisik puedes llamar wait cada vez que el subproceso actual tiene un bloqueo en el objeto en el que wait se llama. Ya sea que use un synchronized block o un método sincronizado depende completamente de usted.

    – bomba

    4 de diciembre de 2014 a las 11:59

  • @BeniBela Pero se puede esperar que sea más lento con seguridad (con respecto a la pregunta original de Huseyin).

    – Tomás

    22 de mayo de 2016 a las 10:49

1646757791 649 ¿Como usar esperar y notificar en Java sin
Jackob

Mientras usa el wait y notify o notifyAll métodos en Java se deben recordar las siguientes cosas:

  1. Utilizar notifyAll en lugar de notify si espera que más de un subproceso esté esperando un bloqueo.
  2. los wait y notify los métodos deben llamarse en un contexto sincronizado. Ver el enlace para una explicación más detallada.
  3. Llama siempre al wait() método en un bucle porque si varios subprocesos están esperando un bloqueo y uno de ellos obtuvo el bloqueo y restableció la condición, entonces los otros subprocesos deben verificar la condición después de que se despierten para ver si necesitan esperar nuevamente o pueden comenzar a procesar .
  4. Usa el mismo objeto para llamar wait() y notify() método; cada objeto tiene su propio candado por lo que llamar wait() en el objeto A y notify() en el objeto B no tendrá ningún sentido.

¿Como usar esperar y notificar en Java sin
Brian Agnew

¿Necesitas enhebrar esto en absoluto? Me pregunto qué tan grandes son sus matrices y si hay algún beneficio en tener un hilo impreso mientras el otro hace la multiplicación.

¿Quizás valdría la pena medir este tiempo antes de hacer el trabajo de subprocesamiento relativamente complejo?

Si necesita enhebrarlo, crearía ‘n’ hilos para realizar la multiplicación de las celdas (quizás ‘n’ es la cantidad de núcleos disponibles para usted), y luego usaría el EjecutorService y Futuro mecanismo para enviar múltiples multiplicaciones simultáneamente.

De esa manera, puede optimizar el trabajo en función de la cantidad de núcleos y está utilizando las herramientas de subprocesamiento de Java de nivel superior (lo que debería facilitarle la vida). Vuelva a escribir los resultados en una matriz de recepción y luego simplemente imprímalos una vez que se hayan completado todas sus tareas futuras.

  • +1 @Greg Creo que deberías echar un vistazo al paquete java.util.concurrent, como lo señaló Brian.

    – ATorras

    20 de mayo de 2009 a las 8:42

  • +1 y también echa un vistazo a este libro que también te enseñará la forma correcta de usar esperar () y notificar () jcip.net

    – Chii

    20 de mayo de 2009 a las 12:44

Digamos que tiene una aplicación de ‘caja negra’ con alguna clase llamada BlackBoxClass que tiene metodo doSomething();.

Además, tiene un observador o un oyente llamado onResponse(String resp) que será llamado por BlackBoxClass después de tiempo desconocido.

El flujo es simple:

private String mResponse = null; 
 ...
BlackBoxClass bbc = new BlackBoxClass();
   bbc.doSomething();
...
@override
public void onResponse(String resp){        
      mResponse = resp;       
}

Digamos que no sabemos lo que está pasando con BlackBoxClass y cuando deberíamos obtener una respuesta, pero no desea continuar con su código hasta obtener una respuesta o, en otras palabras, obtener onResponse llamada. Aquí ingresa ‘Sincronizar ayudante’:

public class SyncronizeObj {
public void doWait(long l){
    synchronized(this){
        try {
            this.wait(l);
        } catch(InterruptedException e) {
        }
    }
}

public void doNotify() {
    synchronized(this) {
        this.notify();
    }
}

public void doWait() {
    synchronized(this){
        try {
            this.wait();
        } catch(InterruptedException e) {
        }
    }
}
}

Ahora podemos implementar lo que queramos:

public class Demo {

private String mResponse = null; 
 ...
SyncronizeObj sync = new SyncronizeObj();

public void impl(){

BlackBoxClass bbc = new BlackBoxClass();
   bbc.doSomething();

   if(mResponse == null){
      sync.doWait();
    }

/** at this momoent you sure that you got response from  BlackBoxClass because
  onResponse method released your 'wait'. In other cases if you don't want wait too      
  long (for example wait data from socket) you can use doWait(time) 
*/ 
...

}


@override
public void onResponse(String resp){        
      mResponse = resp;
      sync.doNotify();       
   }

}

1646757794 503 ¿Como usar esperar y notificar en Java sin
pablojwilliams

Solo puede llamar a notificar sobre objetos en los que posee su monitor. Así que necesitas algo como

synchronized(threadObject)
{
   threadObject.notify();
}

1646757795 1 ¿Como usar esperar y notificar en Java sin
CMPS

notify() también hay que sincronizarlo

¿Como usar esperar y notificar en Java sin
BERGUIGA Mohamed Amina

Le daré un ejemplo simple y le mostraré la forma correcta de usar wait y notify en Java. Entonces crearé dos clases llamadas SubprocesoA & SubprocesoB. ThreadA llamará a ThreadB.

public class ThreadA {
    public static void main(String[] args){
        ThreadB b = new ThreadB();//<----Create Instance for seconde class
        b.start();//<--------------------Launch thread

        synchronized(b){
            try{
                System.out.println("Waiting for b to complete...");
                b.wait();//<-------------WAIT until the finish thread for class B finish
            }catch(InterruptedException e){
                e.printStackTrace();
            }

            System.out.println("Total is: " + b.total);
        }
    }
} 

y para Clase ThreadB:

class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();//<----------------Notify the class wich wait until my    finish 
//and tell that I'm finish
            }
        }
    }

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad