假设我有一个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;
}
}
答案 0 :(得分:1)
您尝试这样做的方式实质上是重新创建幕后的中断,这样您最好只使用中断。话虽如此,如果您使用布尔值volatile
,那么线程将看到更改,其他线程使您的代码应该工作。 :)
中断还有一个优点,即如果它处于某些等待状态,它将唤醒你的线程,因此会导致中断处理更快。请注意,这不能完全依赖,因为在检查标志和进入等待状态之间可能会收到中断 - 在这种情况下,等待仍然需要在看到标志之前超时。
中断和你自己的版本都可以通过发信号通知它应该停止然后让线程自动关闭自己来工作。这是正确的做事方式,因为只是积极地杀死线程会导致各种令人讨厌的副作用,例如半完成处理。