в целом понятно что тут к чему.
Только есть оговорки о особенностях применения синхронизации.
Мне просто хотелось бы услышать мнение о достоинствах и недостатках их, что и в каких случаях лучше всего использовать.
вот самый обычный способ...
package com.journaldev.singleton;
public class ThreadSafeSingleton {
private static ThreadSafeSingleton instance;
private ThreadSafeSingleton(){}
public static synchronized ThreadSafeSingleton getInstance(){
if(instance == null){
instance = new ThreadSafeSingleton();
}
return instance;
}
}
способ ниже был описан на хабре, и на том же хабре писалось что он не работает(прилагалась статья на инглише, но я пока не силен в этом(), подскажет кто что тут не так?
public static ThreadSafeSingleton getInstanceUsingDoubleLocking(){
if(instance == null){
synchronized (ThreadSafeSingleton.class) {
if(instance == null){
instance = new ThreadSafeSingleton();
}
}
}
return instance;
}
и вот тоже есть способ синхронизации через статический метод, в чем его плюс? где лучше использовать?
public class Solution {
public static class OurPresident {
private static OurPresident president;
static {
synchronized (OurPresident.class) {
president = new OurPresident();
}
}
private OurPresident() {
}
public static OurPresident getOurPresident() {
return president;
}
}
}
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Реализация метода getInstance через DCL(double checked locking) существенно улучшает производительность, т.к. уже нет ограничения на количество потоков в методе getInstance(). В данном случае алгоритм работы такой:
1)Проверяем было ли инициализировано поле instance, и если да, то вернем его.
2)Если же поле instance не было инициализировано, то необходимо захватить лок класса Singleton, создать объект, присвоить его полю instance и вернуть.
Синхронизация в данном случае жизненно необходима, чтобы избежать возможности создания дубликатов объекта класса Singleton при выполнении кода в многопоточном окружении. Ускорение же, достигается тем, что после того как объект был создан, сколько угодно потоков сможет зайти в метод getIntance и получить значение поля instance.
Проблема с DCL заключается в том, что у нас нет гарантий того в каком порядке будут выполнены низкоуровневые операции по работе с памятью. В частности возможен следующий сценарий:
1) Поток А входит в метод getInstance, видит что поле instance равно null и переходит в статический блок для его инициализации.
2) Поток B входит в метод getInstance, но т.к. он пока не находится в синхронизированном блоке кода — он может видеть низкоуровневые операции по выделению памяти, созданию объекта и присваиванию ссылки на объект полю instance в произвольном порядке. В частности возможен вариант, когда поток B «успеет увидеть» выделение памяти и присваивание ссылки полю instance, но конструктор будет выполнен не полностью. Таким образом в методе getInstance будет пропущен синхронизированный блок и будет возвращена ссылка на частично сконструированный объект.
Потокобезопасным способом реализации паттерна Singleton без синхронизации является вариант предложенный Би