2013-06-13 1 views
0

Приложение, которое я поддерживаю (передано через многие кодеры), имеет проблему «Продюсер-Потребитель», реализованную с использованием механизма ожидания/уведомления.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.

Как решить эту проблему, используя как можно меньше модификаций?

Спасибо.

ответ

3

Я бы просто использовал ExecutorService, который завершает очередь, управляет вашими потоками и обрабатывает выключение для вас. Если вы это сделаете, почти весь ваш код исчезнет.

Но, чтобы ответить на ваш вопрос, я предлагаю отправить ядовитую таблетку. Специальный объект, который потребитель будет отключать, когда он его получит.

Смежные вопросы