java multithreading exception java-threads

¿Cómo usar wait and notify en Java?



multithreading exception (12)

¿Necesitas enhebrar esto? Me pregunto qué tan grande son tus matrices, y si hay algún beneficio en tener una impresión de hilo mientras que la otra multiplica.

Tal vez valdría la pena medir esta vez antes de hacer el trabajo de enhebrado relativamente complejo?

Si necesita enhebrarlo, crearía ''n'' hilos para realizar la multiplicación de las celdas (tal vez ''n'' es la cantidad de núcleos disponibles), y luego ExecutorService mecanismo ExecutorService y Future para despachar múltiples multiplicaciones simultáneamente .

De esta forma, puede optimizar el trabajo en función del número de núcleos, y está utilizando las herramientas de subprocesamiento Java de nivel superior (que deberían facilitarle la vida). Escriba los resultados de nuevo en una matriz receptora, y luego simplemente imprima esto una vez que todas sus tareas Futuras se hayan completado.

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 la celda [0] [0] antes de la celda [2] [0] incluso si el resultado de [2] [0] está listo primero . Entonces necesito imprimirlo por orden. Así que mi idea es hacer que el hilo de la impresora espere hasta que el multiplyThread notifique que la celda correcta está lista para imprimirse 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 "notify ()" .. Creo que necesito utilizar el sincronizado de manera diferente, pero no estoy seguro de cómo.

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


Digamos que tienes la aplicación ''black box'' con alguna clase llamada BlackBoxClass que tiene el método doSomething(); .

Además, tiene un observador u oyente llamado onResponse(String resp) que será llamado por BlackBoxClass después de un 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 qué está pasando con BlackBoxClass y cuándo deberíamos obtener una respuesta, pero no desea continuar con el código hasta que obtenga una respuesta o, en otras palabras, obtenga onResponse llamada de onResponse . 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 queremos:

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(); } }



Ha guardado correctamente su bloque de código cuando llama al método wait() utilizando synchronized(this) .

Pero no ha tomado la misma precaución cuando llama al método synchronized(someObject) notify() sin usar el bloque guardado: synchronized(this) o synchronized(someObject)

Si consulta la página de documentación de notifyAll() en la clase Object , que contiene los métodos notifyAll() , notifyAll() , notifyAll() , puede ver la precaución siguiente en estos tres métodos

Este método solo debe invocarse mediante un hilo que sea el propietario del monitor de este objeto

Se han cambiado muchas cosas en los últimos 7 años y veamos otras alternativas para synchronized en las siguientes preguntas SE:

¿Por qué usar ReentrantLock si uno puede usar synchronized (this)?

Sincronización vs bloqueo

Evitar sincronizado (esto) en Java?


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

  1. Use notifyAll lugar de notify si espera que haya más de un hilo esperando un bloqueo.
  2. Los métodos de wait y notify deben llamarse en un contexto sincronizado . Vea el enlace para una explicación más detallada.
  3. Siempre llame al método wait() en un bucle porque si hay varios subprocesos 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 espere nuevamente o puede comenzar a procesar.
  4. Use el mismo objeto para llamar al método wait() y notify() ; cada objeto tiene su propio bloqueo, por lo que llamar a wait() en el objeto A y notify() en el objeto B no tendrá ningún sentido.

Para este problema en particular, ¿por qué no almacenar sus diversos resultados en variables y luego, cuando se procesa el último de su subproceso, puede imprimir en el formato que desee? Esto es especialmente útil si va a utilizar su historial de trabajo en otros proyectos.


Para poder llamar a notify() , necesita sincronizar en el mismo objeto.

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


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

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


Uso simple si quieres Cómo ejecutar hilos alternativamente: -

public class MyThread { public static void main(String[] args) { final Object lock = new Object(); new Thread(() -> { try { synchronized (lock) { for (int i = 0; i <= 5; i++) { System.out.println(Thread.currentThread().getName() + ":" + "A"); lock.notify(); lock.wait(); } } } catch (Exception e) {} }, "T1").start(); new Thread(() -> { try { synchronized (lock) { for (int i = 0; i <= 5; i++) { System.out.println(Thread.currentThread().getName() + ":" + "B"); lock.notify(); lock.wait(); } } } catch (Exception e) {} }, "T2").start(); } }

respuesta:

T1:A T2:B T1:A T2:B T1:A T2:B T1:A T2:B T1:A T2:B T1:A T2:B


Voy a ejemplo simple, le mostraré la forma correcta de usar wait y notify en Java. Así que crearé dos clases llamadas ThreadA y ThreadB . 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 Class 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 } } }


podemos llamar a notificar para reanudar la ejecución de objetos en espera como

public synchronized void guardedJoy() { // This guard only loops once for each special event, which may not // be the event we''re waiting for. while(!joy) { try { wait(); } catch (InterruptedException e) {} } System.out.println("Joy and efficiency have been achieved!"); }

reanudar esto invocando notificar sobre otro objeto de la misma clase

public synchronized notifyJoy() { joy = true; notifyAll(); }


notify() necesita ser sincronizado también