2013-12-20 106 views
0

假設我有一個NetThread(定義如下)的對象,名爲nt。我已經初始化並啓動它停止網絡接收器線程

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

現在我希望能夠在執行過程中停止這個線程的任何一點。我可以通過致電nt.interrupt()來完成此操作。

但是,我想我會嘗試做一些更有意義的事情:在NetThread內創建一個名爲StopListening()的方法。

雖然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

你正在嘗試做它基本上是重新創建什麼中斷做幕後所以你可能會更好過只用中斷的方式。話雖如此,如果您製作布爾volatile,以便線程將看到其他線程使您的代碼應該工作的更改。 :)

中斷還有一個優點,它會喚醒你的線程,如果它處於某些等待狀態,所以會導致中斷處理更快。請注意,這不能完全依賴,雖然在檢查標誌和進入等待狀態之間可能會收到中斷 - 在這種情況下,在標誌出現之前等待仍然需要超時。

中斷和你自己的版本通過發信號通知它應該停止,然後讓線程自行關閉。這是做事的正確方式,因爲只是積極殺死線程會導致各種令人討厭的副作用,例如半完成處理。

+1

你能不能請說,爲什麼它更好?我總是使用'while(!isInterrupted())'並調用'myThread.interrupt();'。它工作得很好 – MalaKa

+0

其實你是對的,我正在考慮一個異步殺死,這不是中斷。 –

+0

我編輯了我的答案。 –