Problema de subproceso de Java
-
20-09-2019 - |
Pregunta
Estoy usando múltiples hilos en mi aplicación. Básicamente, tengo un cuadro combinado y al seleccionar la bandeja de entrada, los currículums P1 y P2 se suspenden y al seleccionar el envío, P2 comienza y se detiene P1. A continuación se muestra el código (estoy seguro de que no es perfecto)
public void modifyText(ModifyEvent e) {
if (combo.getText().equals("Inbox"))
{
synchronized(p2)
{
p2.cont = false;
}
table.removeAll();
synchronized(p1)
{
p1.cont = true;
p1.notify();
}
}
else if (combo.getText().equals("Sent"))
{
synchronized(p2)
{
p1.cont = false;
}
table.removeAll();
synchronized(p1)
{
p2.cont = true;
p2.notify();
}
}
}
});
Y para P1 y P2 tengo esto dentro de sus bucles While:
synchronized (this) {
while (cont == false)
try {
wait();
} catch (Exception e) {
}
}
... Como está funcionando ahora (soy un principiante para los hilos). Al presionar enviado en el cuadro combinado, obtengo una ilegaltatemonitorException. ¿Alguien podría ayudarme a resolver el problema por favor?
Gracias y saludos, krt_malta
Solución
El problema está aquí:
synchronized(p1)
{
p2.cont = true;
p2.notify();
}
Tú lo estás haciendo p2.notify()
Cuando no tienes un bloqueo p2
(Debe mantener el monitor para llamar a él). Cambio synchronized(p1)
a synchronized(p2)
. Además, también debe revertir la otra cláusula sincronizada que también es defectuosa. Entonces, como ejemplo:
synchronized(p1)
{
p1.cont = false;
// p1.notify(); <- do you need this here?
}
table.removeAll();
synchronized(p2)
{
p2.cont = true;
p2.notify();
}
Además, su otro código también está un poco incorrecto, es muy mala práctica bloquear dentro de un bucle completo, hacerlo un poco más atómico.
while (!cont) {
synchronized (this) {
try {
wait();
} catch (Exception e) {
}
}
}
Optimización adicional, evite synchronised
si es posible:
if (p1.cont) {
synchronized(p1)
{
p1.cont = false;
// p1.notify(); <- do you need this here?
}
}
table.removeAll();
if (!p2.cont) {
synchronized(p2)
{
p2.cont = true;
p2.notify();
}
}
Hacer el campo contenido volatile
Aquí, y reflejen la otra parte de la declaración IF según corresponda.
EDITAR: Mirando hacia atrás en esto y luchar con un error de concurrencia que me enfrentaba recientemente, cualquiera que implemente este patrón podría enfrentar un problema con una espera infinita, si un objeto que está bloqueado y a medias está siendo mirada por el condicional de la misma manera bucle (esto se debe a que hay una brecha en la que el estado puede cambiar entre evaluar el condicional y la imposición de la declaración de espera). En este caso, coloque el bloque sincronizado en el fuera de del bucle.
Otros consejos
En este código
synchronized(p1)
{
p2.cont = true;
p2.notify();
}
Te estás sincronizando p1
Pero llamando notify()
en p2
, que conduce a la excepción.
No puede esperar en el hilo de despacho de eventos AWT o de lo contrario que mantendrá toda su aplicación. Leer acerca de http://en.wikipedia.org/wiki/event_dispatching_thread
Además, no debe usar hilos sin procesar a menos que realmente sepa lo que está haciendo. Verificar http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html y leer Ejecutores