2013-12-20 3 views
0

이라고하는 유형이 NetThread (아래 정의 됨) 인 것으로 가정합니다. 초기화하고 시작했습니다.네트워크 수신자 스레드 중지

nt = new NetThread(port, rs); 
nt.setDaemon(true); 
nt.setPriority(Thread.MAX_PRIORITY); 
nt.start(); 

이제 실행 중에 언제든지이 스레드를 중지하고 싶습니다. nt.interrupt()에 전화하여이 작업을 수행 할 수 있습니다.

그러나 나는 내게 더 의미있는 것을하려고 노력할 것이라고 생각했다 : 이라고하는 NetThread 내에 메소드를 작성하십시오.

nt이 실행되는 동안 nt.StopListening()이 호출됩니다. 아무것도.

스레드가 계속 실행됩니다. 내가 놓친 게 무엇입니까? 왜이 기능이 작동하지 않습니까?

public class NetThread extends Thread { 

    int port; 

    private static int PAYLOAD_MAX = 10000; 
    private static int NET_SO_TIMEOUT = 0; 
    private RunStats rs; 

    private boolean stopflag = false; 

    private StageCode stage; 

    NetThread(int port_number, RunStats runstats) 
    { 
     rs = runstats; 
     port = port_number; 
     stage = StageCode.STAGE_WAIT; 
    } 

    public synchronized void stopListening() 
    { 
     Log.d(C.DTAG, "stopListening() was called..."); 
     stopflag=true; 
    } 

    @Override 
    public void run() 
    { 
     receiveData(); 
     Log.d(C.DTAG, "Network thread is finished."); 
    } 

    public void receiveData() 
    { 
     // request permission to do network operations in manifest file...done 

     Log.d(C.DTAG, "network thread has started."); 

     // start the network side of things 
     DatagramSocket sock = null; 
     DatagramPacket pkt = null; 

     try 
     { 
      byte[] data = new byte[PAYLOAD_MAX]; 
      sock = new DatagramSocket(port); 
      sock.setSoTimeout(NET_SO_TIMEOUT); 
      pkt = new DatagramPacket(data, 0, PAYLOAD_MAX); 

      while (!stopflag) 
      { 
       Thread.sleep(0); // allow for an interrupt 
       try 
       { 
        sock.receive(pkt); 
        int length = pkt.getLength(); 
        processPayload(pkt.getData(), length); 
       } 
       catch (InterruptedIOException e) 
       { 
        // thrown when a timeout occurs 
        Log.d(C.DTAG, "net: no packets yet"); 
       } 
      } 
      Log.d(C.DTAG, "done receiving."); 
      if (sock != null) sock.close(); 
     } 
     catch (InterruptedException x) 
     { 
      Log.d(C.DTAG, "net: was interrupted."); 
     } 
     catch (SocketException e) 
     { 
      Log.d(C.DTAG, "net: SocketException"); 
      e.printStackTrace(); 
     } 
     catch (IOException e) 
     { 
      Log.d(C.DTAG, "net: IOException"); 
      e.printStackTrace(); 
     } 
     if (sock != null) sock.close(); 
    } 

    public void processPayload(byte[] data, int length) 
    { 
     if (length < 20) return; 

     int sc = data[ 0] & 0x000000FF | data[ 1]<<8 & 0x0000FF00 | data[ 2]<<16 & 0x00FF0000 | data[ 3]<<24 & 0xFF000000; 
     int seq = data[ 4] & 0x000000FF | data[ 5]<<8 & 0x0000FF00 | data[ 6]<<16 & 0x00FF0000 | data[ 7]<<24 & 0xFF000000; 
     int i =  data[ 8] & 0x000000FF | data[ 9]<<8 & 0x0000FF00 | data[10]<<16 & 0x00FF0000 | data[11]<<24 & 0xFF000000; 
     int s =  data[12] & 0x000000FF | data[13]<<8 & 0x0000FF00 | data[14]<<16 & 0x00FF0000 | data[15]<<24 & 0xFF000000; 
     int n =  data[16] & 0x000000FF | data[17]<<8 & 0x0000FF00 | data[18]<<16 & 0x00FF0000 | data[19]<<24 & 0xFF000000; 

     StageCode sc2 = null; 
     switch (sc) 
     { 
     case 20: sc2 = StageCode.STAGE_INIT; break; 
     case 30: sc2 = StageCode.STAGE_TEST; break; 
     case 40: sc2 = StageCode.STAGE_STOP; break; 
     } 

     TestPacketHeader tph = new TestPacketHeader(sc2, seq, i, s, n); 
     rs.RegisterReceivedPacket(tph); 

     if (sc2 == StageCode.STAGE_STOP) stopflag = true; 
    } 

    public synchronized StageCode status() 
    { 
     return stage; 
    } 
} 

답변

1

당신이 기본적으로 당신은 단지 인터럽트를 개시 아마 더 나은 그래서 무대 뒤에서 수행 방해 무엇을 다시하면된다하려고하는 방법. 그렇다면 boolean을 volatile으로 만들면 스레드가 변경 사항을 보게되므로 다른 스레드가 코드를 작동시켜야합니다. :)

인터럽트 또한 특정 대기 상태에있는 경우 스레드를 깨우므로 인터럽트가 더 빨리 처리되는 경향이 있다는 이점이 있습니다. 이것은 플래그를 확인하고 대기 상태로 들어가는 사이에 인터럽트가 수신 될 수 있기 때문에 완전히 의존 할 수는 없으며,이 경우에는 플래그가 표시되기 전에 대기가 여전히 시간 초과되어야합니다.

인터럽트와 자신의 버전은 모두 스레드가 멈춰야한다는 신호를 보내고 스레드가 스스로를 깔끔하게 종료하도록합니다. 그것이 적극적인 방법으로 스레드를 죽이는 것은 반쯤 완료된 프로세싱과 같은 모든 종류의 불쾌한 부작용을 초래할 수 있기 때문에 올바른 방법입니다.

+1

왜 더 나은지 말할 수 있습니까? 나는 항상 while (! isInterrupted())를 사용하고'myThread.interrupt();'를 호출한다. 그것은 단지 잘 작동합니다. – MalaKa

+0

사실 당신 말이 맞습니다. 저는 인터럽트가 아닌 비동기식 킬을 생각하고있었습니다. –

+0

내 대답을 편집했습니다. –