简体   繁体   中英

Server program in Java and passing a reference to a Socket object

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM