java - 调用 LinkedList.add 时线程挂起

标签 java multithreading serversocket

所以我正在编写两个 ServerSocket。一个监听端口 8085 上的 HTTP 请求并将字节输入保存到静态 LinkedList 中,第二个监听端口 8086 并返回静态 LinkedList 中的所有结果。

问题是,当将数据从 ServerSocket:8085 保存到 LinkedList 时,线程挂起,我不确定为什么。

这是主要的监听器类:

import java.net.ServerSocket;
import java.nio.charset.Charset;
import java.util.*;

public class Listener {

    public static LinkedList<byte[]> Calls = new LinkedList<>();

    public static void main(String[] args) {
        Thread callback = new Thread(new ThreadListener());
        callback.start();

        while (true) {
            try (var listener = new ServerSocket(8086)) {
                System.out.println("Listening on 8086...");
                try (var client = listener.accept()) {
                    StringBuffer response = new StringBuffer();
                    response.append("HTTP/1.1 200 OK\r\n\r\n");
                    Iterator<byte[]> iterator = Calls.iterator();
                    while (iterator.hasNext()) {
                        response.append(new String(iterator.next(), Charset.forName("UTF-8")) + "\r\n");
                        iterator.remove();
                    }
                    client.getOutputStream().write(response.toString().getBytes("UTF-8"));
                    client.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }


    }
}

这是 ThreadListener 类:

import java.io.IOException;
import java.net.ServerSocket;
import java.util.Date;

public class ThreadListener implements Runnable {
    @Override
    public void run() {
        while (true) {
            try (var listener = new ServerSocket(8085)) {
                System.out.println("Listening on 8085...");
                try (var socket = listener.accept()) {
                    if (!socket.getInetAddress().getHostAddress().equals("127.0.0.1")) {
                        System.out.println("Not localhost");
                    } else {
                        System.out.println("Its us!");
                    }
                    Listener.Calls.add(socket.getInputStream().readAllBytes());
                    System.out.println("Result collected");
                    Date today = new Date();
                    String httpResponse = "HTTP/1.1 200 OK\r\n\r\n" + today;
                    socket.getOutputStream().write(httpResponse.getBytes("UTF-8"));
                    socket.close();
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

就我的测试而言,我尝试调用 127.0.0.1:8085,然后收到 ERR_CONNECTION_RESET,控制台中的内容如下:

Listening on 8085...
Listening on 8086...
Its us!

Process finished with exit code -1 (I killed the app after 2 mins)

事实是“是我们!”消息已打印,但“结果已收集!”就在 LinkedList.add 没有出现之后,我假设 LinkedList.add 是挂起线程的那个。

问候

编辑:没有人调用 8085(或 8086),我正在浏览器上手动执行此操作。我通过创建一个调用方法而不是直接调用 LinkedList.add 解决了同步问题:

    public static synchronized void addElementsToList(byte[] bytes) {
        Calls.add(bytes);
    }

这确实有效,但调用 8085 套接字每次都会重置连接。

最佳答案

使用浏览器创建请求的测试机制可能也没有帮助,因为 InputStream.readAllBytes()

blocks until all remaining bytes have been read and end of stream is detected, or an exception is thrown. This method does not close the input stream.

来自the documentation 。具体来说,浏览器保持连接打开,因为它期待一些响应。您的服务器正在尝试从连接中读取所有内容直到连接关闭。第 22 条军规(也称为死锁)。

尝试使用 telnet 建立与 localhost:8085 的连接并从客户端关闭连接

telnet 127.0.0.1 8085

^D

其中 ^D 实际上是 [CTRL] 和 [D] 键(例如:注销)

关于java - 调用 LinkedList.add 时线程挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58821488/

相关文章:

java - 从 java ServerSocket 到 iphone 的网络问题(仅在 3g 模式下)

java - Android套接字编程

java - BluetoothServerSocket 不从 accept() 返回

java - 如何管理eclipse git权限?

java - 我应该使用什么 GWT 小部件来显示对象的字符串属性?

python - 为什么 python 要求你在等待条件之前获取锁

linux - 确定线程的堆栈大小和位置

java - aop :aspectj-autoproxy has worked bad at applicationContext

java - getResourceAsStream 在一种情况下返回 null,但在另一种情况下不返回 null,具有相同的类路径

multithreading - ZeroMQ:如何处理 ZeroMQ 节点中与消息无关的异步事件?