2013-06-13 2 views
0

유지 보수 중이거나 (많은 코더를 통과 한) 응용 프로그램은 대기/알림 메커니즘을 사용하여 구현 된 프로듀서 - 소비자 문제가 있습니다.Java에서 대기/통보 메커니즘을 사용하는 프로듀서 - 소비자 스레드 종료

소비자는 응용 프로그램의 "서버"측에서 메시지를 기다린 다음 "클라이언트"측의 메시지를 LDAP 서버로 전달합니다.

여러 연결이 설정/종료되는 문제가 있습니다. 프로듀서 쓰레드는 곱셈을 계속하고 절대로 끝내지 않습니다.

연결이 종료되면 Producer/Consumer 스레드도 모두 종료되어야합니다. 많은 수의 설정/종료 연결을 사용하면 메모리 사용량이 엄청납니다.

코드 :

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() 줄에 매달려 있습니다. 분명히 Producer의 list.notify() (또는 list.notifyAll()?)이 종료 된 후에 배달되지 않으므로 소비자는 alive 부울을 결코 확인할 수 없습니다.

가능한 한 작은 수정을 사용하여이를 해결하는 방법은 무엇입니까?

감사합니다.

답변

3

저는 ExecutorService를 사용하여 큐를 마무리하고 스레드를 관리하며 종료 처리를합니다. 거의 모든 코드가 사라집니다.

그러나 귀하의 질문에 대답하기 위해 나는 독약을 보내는 것이 좋습니다. 소비자가 그것을받을 때 종료 할 특별한 객체.