java - 停止网络接收器线程

标签 java android

假设我有一个 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; 
    }
}

最佳答案

您尝试执行此操作的方式本质上是重新创建中断在幕后所做的事情,因此您可能最好只使用中断。话虽如此,如果您将 boolean 值设置为 volatile ,那么线程将看到其他线程的更改,从而使您的代码应该可以工作。 :)

中断还有一个优点,如果线程处于某些等待状态,它会唤醒线程,因此往往会导致中断处理得更快。请注意,这不能完全依赖,因为在检查标志和进入等待状态之间可能会收到中断 - 在这种情况下,在看到标志之前等待仍然需要超时。

中断和您自己的中断版本都通过向线程发出信号表明它应该停止然后让线程自行关闭来工作。这是正确的做法,因为仅仅积极地终止线程可能会导致各种令人讨厌的副作用,例如半完成的处理。

关于java - 停止网络接收器线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20707052/

相关文章:

java - Eclipse/Java : uncaught exceptions on the EDT suspend execution in EventDispatchThread. 运行()

android - Libgdx 触摸并拖动屏幕上的任意位置以移动 Sprite

android - 如何使用 monkeyrunner 寻找视频 android ics

java - android webrtc VideoCapturerAndroid 由于未设置 applicationContext 而崩溃

java - 用于运行 .jar 的 Shell 脚本可以从终端运行,但不能从 AppleScript 运行

java - 如何修复索引越界错误?

java - 在 Google map 方向中将字符串距离转换为双倍

java - Android教程 thenewboston 空指针异常崩溃

android - 使用 Google Now 启动带参数的应用程序

java - 将数据库中的日期与我从java jsp和sql中的inputtext获得的值进行比较