Вариант Singleton на Java

28 Ноя
2011

Изучив предложенные в статьях «Правильный Singleton в Java» и «Реализация Singleton в JAVA» варианты решений и «пораскинув мозгами», я предположил, что смогу представить еще два похожих друг на друга варианта создания Singleton’а, практически лишенных многих недостатков тех решений, которые были изложены ранее в упомянутых статьях. Но хочу начать с постановки задач, решение которых определит, добились ли мы желаемого результата.

Требования:
1. Потокобезопасность
2. Сериализуемость изменений ссылки на объект-Singleton
3. Управляемость создания объекта в блоке try-catch
4. Создание объекта-Singleton вне конструктора
5. Несериализуемое получение ссылки на объект-Singleton, обеспечивающее лучшую производительность.


Вариант 1
public class Singleton {

    private static volatile Singleton instance;

    static {
        System.out.print("Singleton class Initializator\r\n");
        try {
            InitSingleton();
        } catch (Exception e) {
            System.out.print("Exception occurred\r\n");
        }
    }

    private static synchronized void InitSingleton() {
        if (instance == null) instance = new Singleton();
    }

    public Singleton() {
        System.out.print("Singleton has been initialized\r\n");
    }

    public static Singleton getInstance() {
        return instance;
    }
}


В предложенном варианте, вызов синхронизируемого метода для создания ссылки на объект происходит из так называемого статического инициализатора объекта, который, по сути, выполняется на том же уровне, что и инициализация переменных-членов объекта, выполняется до вызова конструктора и должен быть сериализуем «by design». Но так как моя надежда на самосериализуемость блока-инициализатора не велика, я снабдил статическую ссылку на объект-Singleton модификатором volatile, обеспечивающим непротиворечивость значений статической переменной в разных потоках, а статический метод создания объекта-Singleton снабдил модификатором synchronized, гарантирующим одновременное выполнение данного метода только в одном потоке.

Второй вариант похож на первый тем, что использует тот же принцип инициализации — из блока-инициализатора, но отличен отсутствием модификатора volatile у статической ссылки на объект-Singleton в угоду производительности, а синхронизация создания объекта основывается на блокировке объекта-члена класса с ранее выполненной инициализацией. При этом использована идея, предложенная в комментариях к статье «Правильный Singleton в Java».

Вариант 2
public class Singleton {

    private static Singleton instance;
    private static final Object lock = new Object();
    private static boolean isInitialized = false;

    static {
        System.out.print("Singleton class Initializator\r\n");
        try {
            if (!isInitialized)
                synchronized (lock) {
                    if (instance == null) {
                        instance = new Singleton();
                        isInitialized = true;
                    }
                }
        } catch (Exception e) {
            System.out.print("Exception occurred\r\n");
        }
    }

    public Singleton() {
        System.out.print("Singleton has been initialized\r\n");
    }

    public static Singleton getInstance() {
        return instance;
    }
}
По материалам Хабрахабр.



загрузка...

Комментарии:

Наверх