I am writing a multi-thread program in Java, where i am creating a seperate thread to handle each new client connection. I have:
Socket s;
while(true)
{
s = server.accept();
ClientHandler ch = new ClientHandler(s);
Thread servingThread = new Thread(ch);
servingThread.start();
}
In the ClientHandler thread i have:
public class ClientHandler implements Runnable
{
private Socket s;
public ClientHandler(Socket _Socket, boolean _accepted, BaseStation _bs)
{
this.s = _Socket;
}
If in Java i can't pass an object but only a reference to it, isn't that going to cause a problem, to the s
instance inside ClientHandler whenever server
accepts a new connection? Is it not going to change inside ClientHandler
too and corrupt it? If so, what's the correct way to do it?
See Is Java "pass-by-reference" or "pass-by-value"? to explain.
Passing a new Socket
instance to a new ClientHandler
instance is fine because each ClientHandler
has its own Socket
- changes to the value of the local variable s
do not impact copy of the Socket
instance inside ClientHandler
.
Something like this would cause a problem:
ClientHandler ch = new ClientHandler(s);
Thread servingThread = new Thread(ch);
servingThread.start();
s.someMethod(); // close, read etc.
Because ch.s
and s
both point to the same underlying Socket
object instance.
BTW: spinning off a whole new Thread in a while loop is probably bad unless you're sure those threads will terminate. Probably better to use a ThreadPool.
Your concern is correct because the Socket
object (like any other object in Java) is passed by reference, therefore there is a probability of it being referenced by different modules, or different threads, causing unpredictable behaviour.
However in case of your program there is no problem. The reason is: whenever server accepts a new connection it will create a new Socket
object, which you are then passing to a new instance of ClientHandler
. Therefore every new connection from the client will be served by an independent ClientHandler
instance, so there are no race conditions to the Socket
object to worry about. So you are safe for now.
As a counter-example if you decide to create two ClientHandler
threads to read from the same Socket
object like this ...
s = server.accept();
ClientHandler ch = new ClientHandler(s);
ClientHandler ch2 = new ClientHandler(s);
new Thread(ch).start();
new Thread(ch2).start();
... then you might be in trouble because two ClientHandler
s will get the same reference to the same Socket
object and if both attempt to read from the same socket they will each get only half of the data. Eg if you are receiving a string "hello"
, you might end up with ch
reading "hel"
and ch2
reading "lo"
, or any other combination.
It's a bit confusing, but your code should work as shown. Java first passes by value, and then by reference. IE, you're not passing in a pointer to your " Socket s
", but the actual value of " s
" at the time you're passing it.
To simplify things and eliminate confusion, I'd just remove your forward declaration of " Socket s;
" and make your first line in the loop " Socket s = server.accept();
".
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.