Приложение, которое я поддерживаю (передано через многие кодеры), имеет проблему «Продюсер-Потребитель», реализованную с использованием механизма ожидания/уведомления.Terminating Producer-Потребительские потоки с механизмом ожидания/уведомления в Java
Потребитель ожидает сообщения на стороне «сервера» приложения, а затем пересылает сообщение со стороны «клиента» на сервер LDAP.
Проблема в том, что несколько соединений установлены/завершены. Нити продюсеров просто продолжают размножаться и никогда не прекращаются, когда они должны.
Когда соединение прекращается, как потоки производителя, так и потребители также должны быть прекращены. С большим количеством установленных/завершенных соединений использование памяти становится чудовищным.
Код:
class Producer extends Thread {
public void run() {
long previous = 0;
long last = 0;
long sleeptime = 1;
while (alive) {
try{
last = System.currentTimeMillis();
byte[] aux;
if ((aux = cliente.readmessage()) != null){
sleeptime = 1;
previous = last;
synchronized (list) {
while (list.size() == MAX)
try {
list.wait();
} catch (InterruptedException ex) {
}
list.addFirst(new Messagetimestamped(aux, System
.currentTimeMillis()));
list.notifyAll();
}
}
else{
if (last-previous > 1000)
sleeptime = 1000;
else
sleeptime = 1;
sleep(sleeptime);
}
}
catch (Exception e){
if (lives()){
System.out.println("++++++++++++++++++ Basic Process - Producer");
kill();
nf.notify(false, processnumber);
}
return;
}
}
}
}
class Consumer extends Thread{
public void run() {
while (alive) {
byte[] message = null;
Messagetimestamped mt;
synchronized(list) {
while (list.size() == 0) {
try {
list.wait(); //HANGS HERE!
if (!alive) return;
sleep(1);
}
catch (InterruptedException ex) {}
}
mt = list.removeLast();
list.notifyAll();
}
message = mt.mensaje;
try{
long timewaited = System.currentTimeMillis()-mt.timestamp;
if (timewaited < SLEEPTIME)
sleep (SLEEPTIME-timewaited);
if (s.isClosed() || s.isOutputShutdown()){
System.out.println("++++++++++++++++++++ Basic Process - Consumer - Connection closed!(HLR)");
kill();
nf.notify(false, processnumber);
}
else {
br.write(message);
br.flush();
}
} catch(SocketException e){
return;
} catch (Exception e){
e.printStackTrace();
}
}
}
}
В основном после того, как в живых установлен в false
Производитель получает фактически прекращено. Потребителя нет. Он просто остается висящим на линии list.wait()
. Очевидно, что list.notify()
(или list.notifyAll()
?) От производителя не поставляется после его прекращения, поэтому покупатель никогда не проверяет alive
boolean.
Как решить эту проблему, используя как можно меньше модификаций?
Спасибо.