2013-12-20 66 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

我编辑了我的答案。 –