2015-06-28 96 views
1

我遇到了看起來像死鎖的問題。在讀取期間Java寫入套接字導致死鎖

這是一個客戶端/服務器應用程序。服務器爲每個套接字創建一個線程來讀取並寫入一個線程。

讀取線程獲取客戶端命令,處理它,將結果放入隊列,寫入線程將其取出並寫出。

問題是如果讀線程在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); 
} 

蹤跡:http://pastebin.com/JnsHUFZn

這個例子中的全碼:http://pastebin.com/8RcbxgUw

回答

1

您必須已從一個SocketChannel了服務器端Socket。與這些套接字關聯的流由Channels類分配,並且它們表現出您描述的行爲。堆棧跟蹤確認它。

直接使用java.net.Socket,即在服務器代碼的情況下通過java.net.ServerSocket。在阻止模式下使用SocketChannelServerSocketChannel沒有任何優勢。

+0

謝謝sooo much – iPherian