![](/img/trans.png)
[英]Passing a reference to an object contained within a 'packet' object over a socket in Java
[英]Server program in Java and passing a reference to a Socket object
我正在用Java寫一個多線程程序,在這里我創建了一個單獨的線程來處理每個新的客戶端連接。 我有:
Socket s;
while(true)
{
s = server.accept();
ClientHandler ch = new ClientHandler(s);
Thread servingThread = new Thread(ch);
servingThread.start();
}
在ClientHandler線程中,我有:
public class ClientHandler implements Runnable
{
private Socket s;
public ClientHandler(Socket _Socket, boolean _accepted, BaseStation _bs)
{
this.s = _Socket;
}
如果在Java中我無法傳遞對象,而只能傳遞對其的引用,那么只要server
接受新連接,這都不會對ClientHandler內的s
實例造成問題嗎? 它也不會在ClientHandler
內部更改並破壞它嗎? 如果是這樣,正確的方法是什么?
請參閱Java是“按引用傳遞”還是“按值傳遞”? 解釋。
將新的Socket
實例傳遞給新的ClientHandler
實例很好,因為每個ClientHandler
都有自己的Socket
更改本地變量s
的值不會影響ClientHandler
內部的Socket
實例的副本。
像這樣的東西會導致一個問題:
ClientHandler ch = new ClientHandler(s);
Thread servingThread = new Thread(ch);
servingThread.start();
s.someMethod(); // close, read etc.
因為ch.s
和s
都指向同一個基礎Socket
對象實例。
順便說一句:在while循環中分離出一個新的線程可能是不好的,除非您確定這些線程將終止。 使用ThreadPool可能更好。
您的擔心是正確的,因為Socket
對象(與Java中的其他任何對象一樣)都是通過引用傳遞的,因此有可能被不同的模塊或不同的線程引用,從而導致不可預測的行為。
但是,如果您的程序沒有問題。 原因是:每當服務器接受新連接時,它將創建一個新的 Socket
對象,然后將其傳遞給ClientHandler
的新實例。 因此,來自客戶端的每個新連接都將由一個獨立的ClientHandler
實例提供服務,因此不必擔心Socket
對象的爭用條件。 因此,您現在是安全的。
作為反例,如果您決定創建兩個ClientHandler
線程以從同一 Socket
對象中讀取,就像這樣...
s = server.accept();
ClientHandler ch = new ClientHandler(s);
ClientHandler ch2 = new ClientHandler(s);
new Thread(ch).start();
new Thread(ch2).start();
......那么你可能會遇到麻煩因為有兩個ClientHandler
旨意得到相同的參照相同 Socket
對象,如果都試圖從同一個套接字讀取他們將各獲得只有一半的數據。 例如,如果您收到字符串"hello"
,則可能會以ch
讀取為"hel"
和ch2
讀取為"lo"
或任何其他組合而結束。
這有點令人困惑,但是您的代碼應該按所示工作。 Java首先通過值傳遞,然后通過引用傳遞。 IE瀏覽器,你不是在一個指針傳遞給你的“ Socket s
”,但“實際價值s
”當時你傳遞它。
為了簡化事情並消除混亂,我只刪除了您的“ Socket s;
”的前向聲明,並使循環的第一行成為“ Socket s = server.accept();
”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.