2011-07-30 47 views
0

我有我的(多線程)服務器這個奇怪的問題,當我得到超過500名玩家同時連接時,PrinterWriter需要超過100秒以上(2分鐘),(),有時完成的flush()或打印。PrintWriter verry slow flush()和print()。多線程和套接字。

下面是代碼:

public static void send(Player p, String packet) 
{ 
    PrintWriter out = p.get_out(); 
    if(out != null && !packet.equals("") && !packet.equals(""+(char)0x00)) 
    { 
     packet = Crypter.toUtf(packet); 
     out.print((packet)+(char)0x00); 
     out.flush(); 
    } 
} 

的PrintWriter的是這樣的:

_in = new BufferedReader(new InputStreamReader(_socket.getInputStream())); 
_out = new PrintWriter(_socket.getOutputStream()); 

如果我添加同步到send()方法的關鍵字,整個服務器開始落後於每2秒,如果我不這樣做,那麼一些隨機球員無緣無故開始落後。

任何人有什麼想法?這是從哪裏來的?我該怎麼辦?

+0

由於您無法控制客戶端,因此您必須假設任何數量的客戶端可能會停止閱讀或速度緩慢。發生這種情況時,你必須考慮如何處理這個問題。如果您的客戶正在以足夠快的速度讀取數據,您應該能夠在10毫秒內刷新到500個連接。即緩衝器總是有空閒空間。你不能讓一個慢的客戶放慢每一個客戶的速度。 –

回答

1

打印作家纏繞在插座的輸出流,所以我要去猜測,說套接字輸出緩衝區已滿,所以寫/沖洗通話將被阻塞,直到緩衝區有足夠的空間來容納消息正在發送。如果數據正在被寫入到它更快

該套接字發送緩衝區可能變滿比它可以被髮送到客戶端(或比客戶端可以接收它更快)。

編輯:

附:如果您遇到可伸縮性問題,可能是因爲使用java.io(每個套接字需要一個線程)而不是java.nio(在這種情況下,單個線程可以檢測並執行那些具有待處理數據的套接字的操作) 。 nio旨在支持必須擴展到大量連接的應用程序,但編程模型更加困難。

+0

也許你是對的。我的默認緩衝區大小是:128 000 IN/49 152 OUT。夠了嗎?多少錢就夠了? – Reacen

+0

這並不是關於緩衝區大小,而是關於您寫入套接字的速率,以及客戶端可以傳輸和接收數據的速率。如果第一個速率大於第二個速率,那麼主叫方總是會阻止/等待。在這種情況下,您可能會嘗試發送太多的數據太快;降低更新速率或正在發送的數據量可能會有所幫助。 – JimN

0

的原因是,你send()方法是靜態的,所以寫任何套接字的所有線程正在syncrhonized包含類對象上。使其成爲非靜態的,那麼只有寫入同一個套接字的線程纔會被同步。

+0

儘管該方法看起來像一種不共享任何資源的實用程序方法,因此不需要進行同步。如果多個調用者可能同時操作一個Player實例,那麼調用者可能應該負責在實用程序方法之外同步某些對象,如Player實例本身。 – JimN

+0

你是對的!謝謝!代碼太大,我不得不改變很多東西,但是謝謝。如果它只是一個線程問題,我希望它能解決這個問題。 – Reacen