4

毫无疑问,过去曾以各种形式提出过这个问题,但对于特定场景并没有那么多。

在等待通过 UDP 接收网络消息时停止阻塞的线程的最正确方法是什么。

例如,假设我有以下线程:

public class ClientDiscoveryEngine extends Thread {

    private final int PORT;

    public ClientDiscoveryEngine(final int portNumber) {
        PORT = portNumber;
    }

    @Override
    public void run() {
        try {
            socket = new DatagramSocket(RECEIVE_PORT);

            while (true) {
                final byte[] data = new byte[256];
                final DatagramPacket packet = new DatagramPacket(data, data.length);

                socket.receive(packet);
            }
        } catch (SocketException e) {
            // do stuff 1
        } catch (IOException e) {
            // do stuff 2
        }
    }
}

现在,更正确的方法是使用该interrupt()方法吗?例如添加以下方法:

@Override
public void interrupt() {
    super.interrupt();
    // flip some state?
}

我唯一担心的是,是socket.receive()不是一种不可中断的阻塞方法?我想到的一种方法是在该方法调用中实现上述中断方法,socket.close()然后runSocketException. 或者也许不是while(true)使用在中断方法中翻转的某些状态。这是最好的方法吗?还是有更优雅的方式?

谢谢

4

4 回答 4

4

接收方法似乎不可中断。您可以关闭套接字:javadoc 说:

当前阻塞在receive(java.net.DatagramPacket)此套接字上的任何线程都将抛出 SocketException

您也可以使用setSoTimeout来使接收方法仅阻塞一小段时间。方法返回后,您的线程可以检查它是否已被中断,并在这段时间内重试接收。

于 2011-08-20T14:26:47.997 回答
3

阅读此答案中断等待阻塞操作的线程?

于 2011-08-20T14:18:33.427 回答
2

要停止线程,您不应该在 java 中既不中断也不停止。正如您在问题结尾所建议的那样,最好的方法是让 main 方法内的循环由一个标志控制,您可以根据需要升起该标志。

这是一个旧链接:http: //download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html

其他停止线程的方法已被弃用,并且不提供与此方法一样多的控制。此外,这可能与执行器服务有所不同,我还没有时间去了解它。

另外,如果你想避免你的线程在某些 IO 状态下被阻塞,等待一个套接字,你应该给你的套接字一个连接和读取超时(方法setSoTimeout)。

问候, 斯蒂芬

于 2011-08-20T14:25:53.903 回答
0

这是比较容易的一种。如果它在 UDP 套接字上被阻塞,则向套接字发送一条 UDP 消息,指示接收线程“停止”。

Rgds,马丁

于 2011-08-21T00:52:56.797 回答