JavaTalks.Patterns.Singleton

2,456 views

Published on

Discussing Singleton pattern

1 Comment
1 Like
Statistics
Notes
No Downloads
Views
Total views
2,456
On SlideShare
0
From Embeds
0
Number of Embeds
74
Actions
Shares
0
Downloads
35
Comments
1
Likes
1
Embeds 0
No embeds

No notes for slide

JavaTalks.Patterns.Singleton

  1. 1. Глобальный объект <ul><li>Пулы потоков </li></ul><ul><li>Пулы соединений </li></ul><ul><li>Управление реестрами, конфигурацией </li></ul><ul><li>... </li></ul>
  2. 2. Варианты решения <ul><li>Использовать статический класс ? </li></ul>
  3. 3. Варианты решения <ul><li>Использовать объект ? </li></ul>
  4. 4. Объект? о_О <ul><li>Объект должен создаваться единственный раз </li></ul><ul><li>Объект должен быть доступен другим объектам </li></ul><ul><li>Возможно ли это? </li></ul>
  5. 5. Реализация <ul><li>Конструктор объявлен как private </li></ul><ul><li>Экземпляр создается внутри класса и лишь один раз </li></ul><ul><li>Экземпляр возвращает статический метод </li></ul>
  6. 6. Результат <ul><li>Объект создается лишь один раз </li></ul><ul><li>getInstance() возвращает всегда один и тот же объект </li></ul><ul><li>Объект виден для любого другого объекта </li></ul>
  7. 7. Мне мало! <ul><li>Мало мне, хочу еще… хочу еще чего-нибудь.. хочу еще ленивую загрузку! </li></ul>
  8. 8. Ленивая загрузка?! <ul><li>Ведь, статические члены класса загружаются только при первом обращении к классу… </li></ul>
  9. 9. Не все так просто! <ul><li>Да, instance создастся только при первом обращении к классу, однако не обязательно это обращение произойдет к getInstance() . Наш класс может содержать другие статические члены, например, методы или константы. Тогда экземпляр класса может создаться в любой момент времени… </li></ul>
  10. 10. Singleton on demand
  11. 11. Результат <ul><li>Но что произойдет, если этот Singleton будет работать в многопоточной среде? </li></ul><ul><li>Этот метод не защищен от одновременного обращения к нему нескольких потоков: </li></ul>
  12. 12. Синхронизируем! <ul><li>Теперь наш метод полностью защищен, можем его использовать в своих приложениях! </li></ul>
  13. 13. Low performance <ul><li>Синхронизированные методы снижают производительность: </li></ul><ul><li>Синхронизированный метод запускается в 2-3 раза медленней </li></ul><ul><li>Если один поток зайдет в синхронизированный блок, остальные будут ждать пока первый не выйдет. А количество потоков в крупных приложениях может быть немалым… </li></ul>
  14. 14. Double-check locking <ul><li>Хитрое решение: теперь синхронизация нам потребуется только при создании объекта! </li></ul><ul><li>Это называется double-check locking . </li></ul>
  15. 15. Результат <ul><li>Объект создается лишь один раз </li></ul><ul><li>getInstance() возвращает всегда один и тот же объект </li></ul><ul><li>Объект виден для любого другого объекта </li></ul><ul><li>Lazy initialization </li></ul><ul><li>Потоко-безопасность </li></ul><ul><li>Высокая производительность </li></ul>
  16. 16. Жизнь удалась
  17. 17. ЧЕГО?! <ul><li>Однако этот метод НЕ потоко-безопасен! </li></ul>
  18. 18. Как так?! <ul><li>Но мы синхронизировали блок создания объекта! Как такое возможно?! </li></ul>
  19. 19. Истина печальна… <ul><li>Все бы было хорошо, если б не было так плохо. Дело в том, что double-check locking в Java не работает . Это не баг, это связано с устройством Java Memory Model (JMM). </li></ul><ul><li>Создание объекта происходит в несколько этапов: </li></ul><ul><li>Под объект выделяется память </li></ul><ul><li>Ссылка на объект получает свое значение </li></ul><ul><li>Вызывается конструктор объекта </li></ul><ul><li>Таким образом инициализация объекта может быть еще не завершена, а другой поток поглядит, что ссылка не null и будет использовать его еще сырым. </li></ul>
  20. 20. Бездну не перепрыгнуть <ul><li>Многие пытались обойти эту проблему, однако безуспешно… </li></ul>
  21. 21. Volatile <ul><li>Единственное решение – это использование ключевого слова volatile: </li></ul>Однако, как заметил Allen Holub, volatile может привести к серьезным проблемам с производительностью на мультипроцессорных машинах. К тому же, не во всех JVM volatile реализовано полноценно. Детальней: спецификация JSR 133.
  22. 22. Где же выход? <ul><li>Выходит решения нет?! </li></ul>
  23. 23. Есть! =) <ul><li>Выход нашел Bill Pugh и он так и был назван решением Билла Пью “Initialization on Demand Holder”: </li></ul>
  24. 24. How does it work? <ul><li>Ленивая загрузка обеспечена тем, что обращаемся мы к внутреннему классу только в методе getInstance() </li></ul><ul><li>Синхронизация обеспечена тем, что обратиться к статическому полю мы сможем только к тому моменту, когда класс полностью загружен и его статический блок выполнен </li></ul>
  25. 25. Исключения? <ul><li>Конструктор может выбросить исключение? </li></ul><ul><li>В Java есть понятие статического блока! Забыли? </li></ul>
  26. 26. Можете быть спокойны <ul><li>Больше не придется нервничать </li></ul>
  27. 27. Наслаждайтесь жизнью <ul><li>Не будет подвохов и печальных открытий. Мы нашли идеальный способ, который удовлетворяет все наши потребности. </li></ul>
  28. 28. Мир полон разнообразий… <ul><li>Однако есть еще вариант: </li></ul>
  29. 29. Enum? о_О <ul><li>Да, это enum ! Интересное и вполне работоспособное решение. К тому же решает еще одну проблему, которую мы не рассмотрели, – сериализация. </li></ul>
  30. 30. Enum? о_О <ul><li>Да, это enum ! Интересное и вполне работоспособное решение. К тому же решает еще одну проблему, которую мы не рассмотрели, – сериализация. </li></ul>
  31. 31. Singleton serialization <ul><li>Если мы сериализовали Singleton , а потом дважды десериализовали, то получим ДВА разных объекта. </li></ul>
  32. 32. enum + serialization = love <ul><li>Enum позволяет корректно работать с сериализацией. </li></ul>
  33. 33. УСЬО! <ul><li>Итак, мы рассмотрели все основные виды Одиночек: </li></ul><ul><li>Обычный, без ленивой загрузки </li></ul><ul><li>Однопоточный с ленивой загрузкой </li></ul><ul><li>Многопоточный с синхронизированным методом </li></ul><ul><li>Решение Билла Пью “Initialization on Demand Handler” </li></ul><ul><li>Enum </li></ul><ul><li>Из всех способов вы вольны выбирать любой, который подходит под вашу конкретную ситуацию. </li></ul>
  34. 34. У Одиночки есть много проблем
  35. 35. Подводные камни Одиночки… <ul><li>Невозможность наследования </li></ul><ul><li>“ Single class – single responsibility” violation </li></ul><ul><li>Сложности при тестировании </li></ul><ul><li>Когда одиночка не одинок… </li></ul><ul><li>Java 1.2 + Singleton = вигвам </li></ul>
  36. 36. Singleton sucks <ul><li>Singeton == antipattern? </li></ul>
  37. 37. END

×