Java在读取期间写入套接字会导致死锁

时间:2015-06-28 11:16:30

标签: java multithreading sockets

我遇到了一个看起来像死锁的问题。

它是一个客户端/服务器应用程序。服务器为每个套接字提供了一个要读取的线程和一个要写入的线程。

读取线程接受客户端命令,处理它,将结果放在队列中,写入线程将其关闭并写出来。

问题是如果读取线程在readLine()上阻塞,而写入线程调用println()它也会阻塞,整个事情都会挂起。提供了Stacktrace,看起来像println()尝试锁定readLine()拥有的资源。

有人可以帮忙吗?

简化示例:

ReadThread:

Socket s;
public void run() {
    BufferedReader sin = new BufferedReader(
        new InputStreamReader(s.getInputStream()));
    while (true) {
        String line = sin.readLine();
        if (line == null) { break; }
        String response = "You sent us this: [" + line + "]";
        // add response to queue
    }
}

WriteThread:

Socket s;
public void run() {
        PrintStream sout = new PrintStream(s.getOutputStream(), true);
        while (true) {
            String toWrite = getFromQueue();
            sout.println(toWrite);
            removeFromQueue(toWrite);
        }
}

客户的代码:

public static void main(String[] args) throws IOException {
    int portNumber = 51192;
    Socket s = new Socket("127.0.0.1", portNumber);
    String cmd = "ThisIsATest";
    PrintStream out = new PrintStream(s.getOutputStream(), true);
    BufferedReader in = new BufferedReader(
        new InputStreamReader(s.getInputStream()));
    out.println(cmd);
    String result = in.readLine();
    s.close();
    System.out.println(result);
}

stacktraces:http://pastebin.com/JnsHUFZn

此示例的完整代码:http://pastebin.com/8RcbxgUw

1 个答案:

答案 0 :(得分:1)

您必须拥有Socket的服务器端SocketChannel。与这些套接字关联的流由Channels类分配,它们表现出您描述的行为。堆栈跟踪确认了它。

直接使用java.net.Socket,即在服务器代码的情况下通过java.net.ServerSocket。在阻止模式下使用SocketChannelServerSocketChannel没有任何好处。