【问题标题】:Java Sockets listenerJava 套接字侦听器
【发布时间】:2024-09-29 13:25:02
【问题描述】:

是否适合使用线程获取套接字的 InputStream 接收的对象,然后将它们添加到 ConcurrentLinkedQueue 以便可以从主线程访问它们而不会在轮询输入循环中阻塞?

private Queue<Packet> packetQueue = new ConcurrentLinkedQueue<Packet>();
private ObjectInputStream fromServer; //this is the input stream of the server
public void startListening()
{
    Thread listeningThread = new Thread()
    {
        public void run()
        {
            while(isConnected())    //check if the socket is connected to anything
            {
                try {
                    packetQueue.offer((Packet) fromServer.readObject());  //add packet to queue
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    };
    listeningThread.start();  //start the thread 
}

public Packet getNextPacket()
{
    return packetQueue.poll();  //get the next packet in the queue
}

【问题讨论】:

  • 您需要捕获EOFException 并在获得它时跳出读取循环,除SocketTimeoutException 之外的所有其他IOExceptions 也是致命的。您的join() 调用也不起作用:它只会尝试加入自身,这将永远阻塞,因为线程在join() 中被阻塞时不会死亡。我真的不明白你的建议的意义。
  • 它不断地从服务器读取,直到客户端断开 IE:正在接收多个对象,更准确地说是任意数字
  • 我可以看到你的代码做了什么,我已经对它进行了广泛的评论。我看不到您对队列的建议的重点。你对“适当”的定义是什么?如果没有说明您的要求,这个问题确实无法回答。
  • 作为一种避免用这个循环阻塞主线程,并允许主线程异步访问下一个未读对象的方法。我在问这样做是否可以接受,或者是否有更好的方法。在任意时间异步表示。
  • 但是为什么呢?当队列中没有任何内容时,主线程还要做什么?

标签: java multithreading concurrency network-programming queue


【解决方案1】:

这取决于您需要对将在主线程中使用的这个对象做什么。

如果需要某个时间来处理它,或者如果它会被多次使用,那么您可以将它放入队列或另一个为您保存该对象的类中,但是如果您需要处理它的时间很短,您并且您在处理后不再需要此对象,您实际上不需要使用队列。

关于使用 ConcurrentQueue 太依赖了,你需要命令吗?你需要保证读和写之间的同步吗?

您也可以使用异步套接字来处理多个客户端并在同一个线程中处理,甚至可以从它们中获取对象并放入队列中以进一步处理。

但“适当”很难回答,因为这取决于您需要对这些对象做什么以及如何处理它。

【讨论】:

  • 对象需要按照接收顺序被访问,并且每个对象都有相当长的处理时间。同步队列是因为我有第二个线程将添加到队列中,而主线程将访问它们。
最近更新 更多