![](/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.