Серверная программа на Java и передача ссылки на объект Socket - PullRequest
2 голосов
/ 03 декабря 2011

Я пишу многопоточную программу на 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 я не могу передать объект, а только ссылку на него, не так личтобы вызвать проблему, к экземпляру s внутри ClientHandler всякий раз, когда server принимает новое соединение?Разве это не изменится и внутри ClientHandler и испортит его?Если да, то как правильно это сделать?

Ответы [ 3 ]

2 голосов
/ 03 декабря 2011

См. Является ли Java "передачей по ссылке" или "передачей по значению"? для объяснения.

Передача нового экземпляра Socket в новый экземпляр ClientHandler - это нормально, поскольку каждый ClientHandler имеет свой собственный Socket - изменения значения локальной переменной s не влияют на копию Socket экземпляр внутри ClientHandler.

Что-то вроде , это может вызвать проблемы:

ClientHandler ch = new ClientHandler(s);
Thread servingThread = new Thread(ch);
servingThread.start();

s.someMethod(); // close, read etc.

Поскольку ch.s и s оба указывают на один и тот же базовый Socket экземпляр объекта.

Кстати: вращение целого нового потока в цикле while, вероятно, плохо, если вы не уверены, что эти потоки прекратятся. Вероятно, лучше использовать ThreadPool.

2 голосов
/ 03 декабря 2011

Ваша проблема правильна, потому что объект 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 s получат одинаковую ссылку на тот же Socket объект, и если оба попытаютсядля чтения из одного сокета они получат только половину данных.Например, если вы получаете строку "hello", вы можете получить ch с чтением "hel" и ch2 с чтением "lo" или любую другую комбинацию.

1 голос
/ 03 декабря 2011

Это немного сбивает с толку, но ваш код должен работать так, как показано.Java сначала передается по значению, а затем по ссылке.То есть, вы не передаете указатель на «Socket s», но фактическое значение «s» в момент его передачи.

Чтобы упростить вещи и устранить путаницу,Я бы просто удалил ваше предварительное объявление "Socket s;" и сделал бы вашу первую строку в цикле "Socket s = server.accept();".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...