¿Cómo usar esperar y notificar en Java sin IllegalMonitorStateException?
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 pedido. Entonces, mi idea es hacer que el hilo de la impresora espere hasta que le multiplyThread
notifique que la celda correcta está lista para imprimirse y luego imprimirá printerThread
la celda y volverá a esperar y así sucesivamente.
Entonces 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 tira 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)
La línea 49 multiplyThread
es "notificar()". Creo que necesito usar 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.
Para poder llamar a notify() necesitas sincronizar en el mismo objeto.
synchronized (someObject) {
someObject.wait();
}
/* different thread / object */
synchronized (someObject) {
someObject.notify();
}
Al utilizar los métodos wait
y notify
o notifyAll
en Java se deben recordar las siguientes cosas:
- Úselo
notifyAll
en lugar denotify
si espera que más de un subproceso esté esperando un bloqueo. - Los métodos
wait
ynotify
deben llamarse en un contexto sincronizado . Consulte el enlace para obtener una explicación más detallada. - Siempre llame 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 despertarse para ver si necesitan esperar nuevamente o puede comenzar a procesar. - Utilice el mismo objeto para llamar
wait()
ynotify()
método; cada objeto tiene su propio bloqueo, por lo que llamarwait()
al objeto A ynotify()
al objeto B no tendrá ningún sentido.
¿Necesitas enhebrar esto? Me pregunto qué tan grandes son sus matrices y si hay algún beneficio en tener un hilo impreso mientras el otro realiza la multiplicación.
¿Quizás valdría la pena medir este tiempo antes de realizar el trabajo de enhebrado relativamente complejo?
Si necesita enhebrarlo, crearía 'n' subprocesos para realizar la multiplicación de las celdas (quizás 'n' sea la cantidad de núcleos disponibles para usted) y luego usaría el mecanismo ExecutorService y Future para enviar múltiples multiplicaciones simultáneamente. .
De esa manera, puede optimizar el trabajo en función de la cantidad de núcleos y estará utilizando las herramientas de subprocesamiento de Java de nivel superior (que deberían hacer la vida más fácil). Vuelva a escribir los resultados en una matriz de recepción y luego simplemente imprímala una vez que se hayan completado todas sus tareas futuras.