Java:具有两个不同输入源的多线程并作出反应

时间:2016-04-20 05:32:47

标签: java multithreading sockets udp multicastsocket

关于StackOverflow的第一个问题,如果我不正确地问这个问题,请原谅。

基本上,我正在编写一个无限制地侦听多播地址的多播客户端,直到用户在控制台中键入“退出”为止。我发现为MulticastSocket设置SO_TIMEOUT,检查是否已键入“quit”,然后返回到receive方法调用并不真正起作用,因为可以在超时后立即发送数据包并检查控制台块。所以我认为最好的选择是简单地让2个线程进入一个侦听套接字并阻塞直到它收到一些东西,另一个线程监听控制台直到被告知退出。我唯一的问题是我不确定如何让控制台监听线程告诉套接字线程关闭套接字并终止。 System.end()可以工作,但我担心我会打开套接字等等。

TLDR;有没有办法让类的main方法启动一个线程,然后一旦该线程结束就以特定的方式响应?我需要在一个线程上监听控制台,在另一个线程上监听MulticastSocket,或者只在客户端类的主体中监听。

谢谢大家。

1 个答案:

答案 0 :(得分:1)

我会调用Socket.close()来关闭套接字。这将在该线程中产生IOException。所以在这之前我会设置一个像closed = true;这样的标志,让其他线程在打印错误之前检查一下,如果你已经关闭则不要打印IOException。这样的事情。

public class SocketListener implements Runnable, Closeable {
    final MulticastSocket socket;
    final Consumer<DatagramPacket> packetConsumer;
    volatile boolean closed;

    public SocketListener(MulticastSocket socket, Consumer<DatagramPacket> packetConsumer) {
        this.socket = socket;
        this.packetConsumer = packetConsumer;
    }

    @Override
    public void run() {
        DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
        try {
            while(!closed) {
                socket.receive(packet);
                packetConsumer.accept(packet);
            }
        } catch (IOException e) {
            if (!closed)
                e.printStackTrace();
        }
    }

    @Override
    public void close() throws IOException {
        closed = true;
        socket.close();
    }
}
例如,在主线程中你可以做到

MulticastSocket socket = ...
Consumer<DatagramPacket> packetConsumer = ...
try (SocketListener listener = new SocketListener(socket, packetConsumer)) {
    boolean finished = false;
    do {
        // read from the console
        if (some condition)
            finished = true;
    } while(!finished);
} // calls close() for you.