调用LinkedList.add时线程挂起

时间:2019-11-12 15:12:17

标签: java multithreading serversocket

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

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

这是侦听器的主要类:

int main() 
{

        long int id;
        float grade,age;
        char name[40],city[40],country[40],line[100]="3888914775 Itzel_Gardean 21 26 Iran Tehran";

        int read_items = sscanf(line,"%ld %s %f %f  %s %s",&id,name,&age,&grade,country,city);

        printf("readed line is: %ld %s %f %f %s %s. sscanf() read %d items\n",id,name,grade,age,country,city,read_items);

}

这是ThreadListener类:

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();
            }

        }


    }
}

对于我的测试,我尝试调用127.0.0.1:8085,并且收到ERR_CONNECTION_RESET,控制台中的所有内容如下:

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();
            }
        }
    }
}

“这就是我们!”消息已打印,但“结果已收集!”紧接着LinkedList.add失败之后,我才假设LinkedList.add是挂线程的线程。

致谢

编辑:没有人打电话给8085(或8086),我正在浏览器中手动进行操作。我通过创建一种调用方法而不是直接调用LinkedList.add来解决了Syncronization问题:

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

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

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

2 个答案:

答案 0 :(得分:1)

LinkedList不是synchornizedas highlighted in the documentation

您可以手动处理同步,使用同步列表或并发列表。也许还有其他方法,但就目前而言,只需保持简单即可。

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

// or

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

答案 1 :(得分:1)

您使用浏览器创建请求的测试机制在这里也可能无济于事,例如InputStream.readAllBytes()

  

阻塞,直到读取完所有剩余字节并检测到流的末尾或引发异常为止。此方法不会关闭输入流。

来自the documentation。具体来说,浏览器会保持连接打开状态,因为它期待某些响应。您的服务器正在尝试从连接读取所有内容,直到连接关闭。捕获22(又名死锁)。

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

telnet 127.0.0.1 8085

^D

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