2013-02-13 2 views
2

내 프로그램이 멈추기 전까지는 더 적은 메시지를 보내고 약 20 초 후에 실행된다. 나는 스레드 덤프를 만들었어요 그리고 스레드가 중지 코드의 다음 줄에 나 포인트 :쓰레드는 소켓/프린트 라이더 상호 작용에 매달린다.

if(s.isClosed() || !s.isConnected() || s.isInputShutdown() || s.isOutputShutdown() || out == null || out.checkError()) { 

"class xxx.xxx.xxx" prio=10 tid=0x000000000200d800 nid=0x6e7f waiting for monitor entry [0x00007f63172b6000] 
    java.lang.Thread.State: BLOCKED (on object monitor) 
     at java.io.PrintWriter.flush(PrintWriter.java:291) 
     - waiting to lock <0x00000000ec810218> (a java.io.BufferedWriter) 
     at java.io.PrintWriter.checkError(PrintWriter.java:330) 

이 스레드 덤프 정보는 지적 내 스레드 덤프의 일부입니다 문제는 Printwriter.checkError()에 있습니다. 그러나 나는 그것이 왜 여기서 멈출 것인지 이해할 수 없다.

아래 코드는 상황에 맞는 코드입니다.

public void parseMessage(final byte[] bytes) { 
    synchronized (receivers) { 
     for (final Socket s : receivers.keySet()) { 
      final PrintWriter out = receivers.get(s); 
      if(s.isClosed() || !s.isConnected() || s.isInputShutdown() || s.isOutputShutdown() || out == null || out.checkError()) { 
       receivers.remove(s); 
       failedToConnect(s.getInetAddress().getHostAddress(), s.getPort()); 
       continue; 
      } 
      queue.add(out, bytes); 
     } 
    } 
} 

업데이트 14 januari (수신기가 Map<Socket, PrintWriter>이다) (그리니치 표준시 10시 + 1) :

대신하는 차 BufferedWriter

업데이트 14 januari와 PrintWriter (그리니치 표준시 16시 +1) :

나는 더 많은 테스트를 해봤지만 일부 네트워크/독자들이 문제를 일으키고 있습니다. 응용 프로그램은 일부 외부 네트워크 (인터넷을 통해)의 일부 독자에게 내부 네트워크 및 일부 독자에게 데이터를 보냅니다. 이것이 정확히 무엇을 일으키는지는 아직까지는 알 수 없지만 몇 가지 단서가 있습니다. 몇 가지 다시 시작한 후 두 네트워크 간의 연결이 닫히지 않았으므로 연결이 열린 상태를 유지할 수있었습니다. 나는 아직도 정확히 무슨 일이 일어나고 있는지 모르지만 그것이 네트워크 문제라고 생각합니다. 서버 측에서는 연결은 "FIN_WAIT1"에 있고 판독기 쪽에서는 "ESTABLISHED"로 유지됩니다. 그것은 신호가 그것을 닫으려면 전송되었습니다조차도 독자가 연결을 닫으려고 신호하지 않을 것 같습니다. 스레드가 차단

+1

사이드 댓글 :'for (최종 Map.Entry <소켓, PrintWriter> 전자 : receivers.entrySet()) {최종 PrintWriter 아웃 = e.getValue(); 최종 소켓 s = e.getKey();'는 좀 더 효율적입니다. – assylias

+0

Thx가이를 지적했습니다. – Kevin

답변

0

의이 대부분 쓸데없는 일련의 당신이 how-to-analyze-java-thread-dumps

+0

나는 동의한다.하지만 checkError가 호출 될 때 프린트 작가가 내용을 플러시하지 못하게하는 원인은 무엇일까? 데이터가 기록 된 클라이언트는 완전히 도달 할 수 있습니다. 스위치 등에서 운영 체제 문제 나 네트워크 문제를 조사해야합니까? 귀하의 회신에 대해서는 – Kevin

1
if(s.isClosed() || !s.isConnected() || s.isInputShutdown() || s.isOutputShutdown() || out == null || out.checkError()) 

가 발생하는 것과 매우 유사이 링크를 살펴 가 I/O 요청을 기다리고 가능성 테스트.

  • 소켓이 닫혀 있으면 코드의이 부분에 전혀 들어가서는 안됩니다.
  • 소켓이 연결되어 있지 않은 경우에도 마찬가지입니다.
  • 입력을 위해 소켓을 종료 한 경우 쓸 수 없다는 의미는 아닙니다.
  • 출력을 위해 소켓을 종료 한 경우이 코드 부분에 있어서는 안됩니다.
  • out이 null 인 경우 코드의이 부분에 있어서는 안됩니다.
  • 테스트는 checkError()이 좋지만 실제로 네트워크를 통해 PrintWriter을 사용하지 않아야합니다. 예외가 발생하기 때문입니다. BufferedWriter을 사용하는 것이 더 좋을 것이며 여기에서하는 것처럼 다음 글쓰기보다는 예외가 발생하면 잘못 될 것이라고 예외를 알려주십시오.

당신은 또한이 Socket. 마찬가지로, Socket.isConnected()는 당신이 Socket,를 연결하거나 이미 생성자, 또는 ServerSocket.accept()를 통해 연결 받았는지를 알 수 닫은 여부 Socket.isClosed() 만 알려줍니다 것을 이해할 필요가있다. isInputShutdown()isOutputShutdown().에 대해서도 마찬가지입니다. Socket.에 한 일만 알려줍니다. 연결의 상태에 대해 알려주는 방법은 없습니다.

이 스레드 덤프 정보는 문제가 Printwriter.checkError()에 있음을 나타냅니다. 그러나 나는 그것이 왜 여기서 멈출 것인지 이해할 수 없다.

스택 추적도 알려줍니다으로, 당신이 독자를 오버런 것을 의미하는 경우 블록 것을 flush().를 호출하고, TCP는 그를 자신의 소켓에 무료 버퍼 공간에 일부 데이터를 읽기 위해 기다리고 있습니다, 때문에 수신 버퍼 따라서 소켓 보내기 버퍼. 그 때까지 기본 send()이 차단됩니다. 독자의 속도를 높이는 것 외에는 할 수있는 일이 없습니다.

+0

Thx입니다. 나는'Printwriter'를 대체하고 소켓 체크를 제거하고'BufferedWriter'에 쓸 때 예외를 잡을 것입니다. 내 독자는 충분히 빠르지 만. 나는 독자가 처리 할 수있는 것의 1 %도 쓰고 있지 않습니다. 오늘 오후에 우리 서버에서 더 많은 테스트를 수행하려고합니다. 플러시 메서드를 차단하는 무언가를 찾을 수 있기를 바랍니다. 아마도 실패한 스위치/네트워크 카드 또는 그와 같은 것이 플러시를 차단하는 원인이 될 수 있습니다. – Kevin

+1

@Kevin 증거가 당신에 대한 것입니다. 실패한 네트워크 요소는 궁극적으로 IOException을 일으키지 만, 스레드 덤프를 가져오고 질문 할 수있는 충분한 블록이 아닙니다. – EJP