Java-синглтон-класс и многопоточность - PullRequest
0 голосов
/ 28 февраля 2019

Народ - у меня есть вспомогательный класс, задача которого - построить несколько сообщений на основе параметров.Класс сам по себе не имеет никаких личных данных (кроме экземпляра конечно).

public class RequestBuilder {
    private static RequestBuilder instance = new RequestBuilder();

    private RequestBuilder() {}

    public static RequestBuilder getInstance() {
        return instance;
    }

    public SetRequest buildSetRequest(Path prefix,
                                      Path path,
                                      ConfigEntity configEntity,
                                      Any protoAnyData) {
        .....
        .....
        return setRequest;
    }

    public GetRequest buildGetRequest(Path prefix,
                                      Path Path,
                                      RetrieveRequestEntity retrieveRequestEntity,
                                      Encoding encoding) {
        .....
        .....
        return getRequest;
    }
}

Я понимаю, что одноэлементные классы не являются многопоточными.В этом случае, что происходит, когда 2 потока пытаются выполнить buildSetRequest () одновременно?

Спасибо за ваше время.

РЕДАКТИРОВАТЬ: Исходя из моей потребности,и как предложено @BoristheSpide в комментариях ниже, я собираюсь сделать этот класс служебным классом со следующими изменениями: 1. Сделать его окончательным.2. Сделайте методы статичными.3. Удалите все одиночные ссылки.

public final class RequestBuilder {

    private RequestBuilder() {}

    public static SetRequest buildSetRequest(Path prefix,
                                      Path path,
                                      ConfigEntity configEntity,
                                      Any protoAnyData) {
        .....
        .....
        return setRequest;
    }

    public static GetRequest buildGetRequest(Path prefix,
                                      Path Path,
                                      RetrieveRequestEntity retrieveRequestEntity,
                                      Encoding encoding) {
        .....
        .....
        return getRequest;
    }
}

Я оставляю исходный код как есть, потому что он все еще действителен и дает контекст для комментариев и ответов на этот вопрос.

1 Ответ

0 голосов
/ 28 февраля 2019

В этом случае не слишком много, потому что ваш конструктор пуст (то, что другие называют как нет общего состояния ).Проблемы начинаются, когда у вас есть несколько частных переменных экземпляра, которые вы должны инициализировать.В этом случае вам нужна некоторая защита, например, проверка doble:

private static volatile RequestBuilder instance;

private RequestBuilder() {}

public static RequestBuilder getInstance() {
    if (instance == null) {
        synchronized (RequestBuilder.class) {
            if (instance == null) {
                instance = new RequestBuilder();
            }
        }
    }
    return instance;
}

. Причина в том, что поток может быть приостановлен в любое время.Если текущий поток, создающий экземпляр, приостановлен, а другой приходит, может быть половина инициализированных переменных экземпляра, и объект может оказаться в поврежденном состоянии.

РЕДАКТИРОВАТЬ: О buildSetRequest()

Код находится внутри метода, если этот метод сам создает свои собственные экземпляры или работает с поточно-безопасными классами, проблем не будет.

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