2011-11-03 2 views
0

내 스윙 채팅 응용 프로그램에서 데이터 그램 소켓을 통해 무제한으로 수신 대기하는 스레드가 있습니다. 나는이 응용 프로그램을 닫을 때, 나는 다음과 같은 코드가 실행 한 : 그러나Thread.interrupt를 사용하여 Java에서 스레드 죽이기

listenThread.interrupt(); 
socket.close(); 

를 소켓이 닫힐 때와 같이, 스레드를 중지하지 않는 것 중단, 루프 듣고 계속 소켓 때문에 예외를 throw 폐쇄되었습니다. 소켓을 안전하게 닫을 수 있도록 스레드를 올바르게 종료하려면 어떻게해야합니까?

+0

연결을 수신하는 데 사용하는 코드를 게시 할 수 있습니까? 그것은 다음과 같습니다 : while (running) {sock = sSock.accept(); ...}? –

+1

* interrupt() *는 소켓 읽기 또는 쓰기와 같은 I/O 작업을 인터럽트하는 데 사용할 수 없습니다. I/O를 중단하려면 소켓을 닫는 것이 좋습니다. 스레드가 IOException을 수신 한 후 스레드가 [중단됨]인지 확인해야합니다 (http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#isInterrupted%28%29). 그러는 동안 정상적으로 종료하십시오. – JimmyB

+0

@HannoBinder, 답안에 이것을 넣었어야합니다. 왜 코드가 옳은지에 대한 훌륭한 설명입니다. –

답변

4

interrupt()은 소켓 읽기 또는 쓰기와 같은 I/O 작업을 방해하는 데 사용할 수 없습니다. I/O를 중단하려면 소켓을 닫는 것이 좋습니다. 스레드가 IOException을 수신 한 후 잠시 중단되었는지 확인한 다음 정상적으로 종료해야합니다. 당신의 I/O 스레드에서 코드

예 :

while(!Thread.currentThread().isInterrupted()) { 
    try { 
    doRead(); 
    } catch (IOException ioe) { 
    // Log exception or whatever 
    } 
} 
+0

사실 NIO에서는 맞지 않습니다. – Voo

0

interrupt()은 스레드에게 누군가를 중지시키려는 의도만을 알립니다. 제대로 종료하려면 스레드에 따라 달라집니다. 스레드가 모니터에서 대기 중이면 InterruptedException을 수신합니다. 그렇지 않으면 현재 스레드에서 isInterrupted()을 확인할 수 있습니다. 그러나 IO에서 대기 중이면 운이 좋지 않을 수 있으며 유일한 선택은 소켓 시간 초과가 만료 될 때까지 기다리는 것입니다. 그런 다음 스레드가 인터럽트되었는지 확인하고 소켓을 닫습니다.

0

예외를 던지고 경우는, 그것을 잡을와 UDP를 종료 스레드를 참조하십시오. 소켓을 다른 스레드에서 닫을 때 예외를 throw하는 것은 예상됩니다 -이를 사용하십시오!

실패한 경우 인터럽트 된 플래그를 설정하고 종료를 요청하는 스레드의 소켓에서 로컬 TCP 스택의 데이터 그램을 보내서 UDP read()를 반환하십시오. UDP는 비 연결 메시지 서비스이며 같은 상자에있는 다른 스레드로부터 데이터 그램을 수신하게되어 매우 행복합니다. 데이터 그램은 종료 명령을 포함 할 수 있습니다. 그렇지 않으면 모든 read() 반환 후에 isInterrupted 플래그를 확인할 수 있습니다.

0

난 당신이에게 쉬운 방법을 구현했던 가정거야 :

DatagramSocket s = new DatagramSocket(port); 
DatagramPacket p = new DatagramPacket(new byte[256], 256); 
s.receive(p); 

지금, Javadoc을보고 해 InterruptedException을 던져 DatagramSocket.receive()를 얻을 수있는 방법은 없습니다. 소켓을 닫는 것이 듣기를 멈추게하는 유일한 방법입니다.

보다 나은 구현은 DatagramSocket.setSoTimeout(int)을 2 초와 같이 작은 것으로 사용하여 DatagramSocket에서 시간 초과를 설정 한 다음 서버가 중단되었는지 확인하는 것이 었습니다. 따라서 서버 코드에 대해 다음과 같이 끝낼 것입니다 (예외 처리는하지 않음).

DatagramSocket s = new DatagramSocket(port); 
s.setSoTimeout(2000); // 2 second time out 

while(running){ // boolean running flag, check for interrupt here 
    try{ 
     DatagramPacket p = new DatagramPacket(new byte[256], 256); 
     s.receive(p); 
     //do stuff 
    } catch (SocketTimeoutException e){ 
     //timed out 
    } 
}//end while 
+0

소켓을 사용하지 않으려 고해도 소켓이 시간 초과되는 것을 원하지 않습니다. 아무리 길어도 메시지를 릴레이 할 수 있기를 바랍니다. –

+0

시간을 초과하거나 종료를 확인한 다음 종료하거나 계속 듣거나 소켓을 닫고 IOException이 발생할 수 있습니다. 나는 이것을 할 수있는 방법이 없다고 확신한다. – VolatileDream

+0

소켓이 수신 대기하지 않는 시간은 최소화되므로 응용 프로그램에 문제가 발생하지 않아야합니다. – VolatileDream