Синглтонский шаблон легче всего понять и самый простой способ написания вручную кода в шаблоне проектирования, но в качестве вопроса интервью он часто используется в качестве вопроса об собеседовании. Как правило, синглтоны написаны пятью способами: ленивый, голодный, двойная проверка, статические внутренние классы и перечисление. Чтобы записать процесс обучения, здесь было составлено несколько общих методов написания синглтонов.
Бронза 5: (ленивый, но нить небезопасна)
Когда его спросили о внедрении синглтонского шаблона, первая реакция многих людей - написать следующий код, включая те же учения в учебниках.
Public Class Singleton {Private Static Singleton Extance; private singleton () {} public static singleton getInstance () {if (exance == null) {ancess = new singleton (); } return Encement; }}Этот код прост и прост, и использует режим задержки загрузки, но потоки не являются безопасными. Вызов метода getInstance () в многопоточной среде может привести к тому, что несколько потоков введены блок кода программы в операторе if.
Ленивый стиль: синхронизированный (ленивый, загруженный, безопасный, но не эффективный)
Чтобы решить вышеупомянутую проблему, самый простой способ - установить весь метод GetInstance () для синхронизации.
Public Class Singleton {Private Static Singleton Extance; private singleton () {} public static synchronized singleton getInstance () {if (ancess == null) {ancess = new singleton (); } return Encement; }}Хотя он безопасен для потока и отсроченную нагрузку, она не эффективна. Потому что в любое время может быть только один поток, вызывающий метод GetInstance (). Тем не менее, синхронизированная операция должна потребоваться только при первом вызове, то есть когда объект экземпляра Singleton создается в первый раз. Этот шаблон приводит к тому, что только один поток доступа к методу getInstance () даже после создания Синглтона, что может привести к потенциальным проблемам производительности. Это приводит к двойной проверке блокировки.
Голодный стиль: статическое финальное поле (не загруженное безумным)
Этот метод очень прост, потому что экземпляр синглтона объявляется статическим окончательным и инициализируется, когда класс загружается в память в первый раз, поэтому создание объекта экземпляра безопасно (гарантированно реализацией JVM).
открытый класс Singleton {// Инициализировать частный статический финальный экземпляр Singleton = new Singleton (); private singleton () {} public static singleton getInstance () {// singleton со статическим экземпляром возврата статического завода; }}Это не ленивый режим загрузки, экземпляр будет инициализирован с самого начала после загрузки класса, даже если клиент не вызывает метод getInstance (). Это приведет к некоторым ограничениям использования: например, создание экземпляра Singleton зависит от параметров или файлов конфигурации. Перед getInstance () должен быть вызван определенный метод для установки параметров, чтобы этот метод написания синглтона не использовался. Аналогичные методы включают в себя:
Public Class Singleton {public Static Final Singleton Extance = new Singleton (); // Singleton с публичным финальным полевым частным Singleton () {}} // <Эффективный Java> Page 14 рассказывает разницу между нимиДвойная проверка блокировки + летучая (ленивая загрузка, безопасная, но неясная)
Двойная проверка блокировки - это метод блокировки с использованием синхронных блоков. Программисты называют это двойной блокировкой проверки, потому что будет два экземпляра проверки == NULL, один раз за пределами блока синхронизации и один раз внутри блока синхронизации. Зачем нам нужно снова проверить в блоке синхронизации? Поскольку несколько потоков могут входить, если за пределами блока синхронизации вместе, если в блоке синхронизации не проводится вторичная проверка, будут генерироваться множественные объекты экземпляров.
public static singleton getsingleton () {if (ancess == null) {// single chested synchronized (singleton.class) {if (exant == null) {// double -проверенный экземпляр = new singleton (); }}} return Encement;}Этот код выглядит идеально, но, к сожалению, он проблематично. Главное, что предложение экземпляры = new Singleton (). Это не атомная операция. На самом деле, это предложение в JVM делает примерно следующие 3 вещи.
Тем не менее, существует оптимизация переупорядочения инструкций в компиляторе JVM JIT. Другими словами, порядок второго и третьего шага выше не может быть гарантирован, а окончательный порядок выполнения может быть 1-2-3 или 1-3-2. Если это последнее, он будет превзойден потоком 2, прежде чем выполнение 3 и 2 не будет выполнено. В настоящее время экземпляр уже не нулевой (но не инициализирован), поэтому поток 2 напрямую вернет экземпляр, затем используйте его, а затем, естественно, сообщит об ошибке. Чтобы сделать это, нам нужно объявить переменную экземпляра изменчивой.
открытый класс Singleton {частный летучий статический экземпляр Синглтона; // объявить как летучим частным singleton () {} public static singleton getsingleton () {if (exance == null) {synchronized (singleton.class) {if (ancess == null) {exance = new singleton (); }} return Encement; }}Тем не менее, важно отметить, что есть все еще проблемы с блокировкой летучих проверок с двойной проверкой в версиях до Java 1.5. Эта проблема была исправлена только в Java 1.5, поэтому после этого вы можете использовать летучие.
Статический внутренний класс: йод, инициализация по запросу держателя по запросу
Этот шаблон сочетает в себе статические внутренние классы Java и многопоточные знания синхронизации по умолчанию и умно реализует как задержку, так и безопасность потока.
Public Class Singleton {private singleton () {} private Static Class Lazyholder {Private Static Final Singleton Extance = new Singleton (); } public static singleton getInstance () {// из Википедии return LazyHolder.Instance; }}Статический внутренний класс эквивалентен статической части его внешнего класса. Его объекты не зависят от внешних объектов класса, поэтому их можно создать напрямую. Статические внутренние классы будут воспроизведены только тогда, когда они используются в первый раз.
Многопользовательская блокировка синхронизации по умолчанию
Как мы все знаем, в многопоточной разработке, чтобы решить проблему параллелизма, в основном используется синхронизированный для добавления мутексов для управления синхронизацией. Но в некоторых случаях JVM уже неявно выполняет синхронизацию для вас, и в этих случаях нет необходимости вручную выполнять контроль синхронизации. Эти ситуации включают :
1. При инициализации данных статическим инициализатором (инициализатор на статическом поле или в статическом {} блоке)
2. При доступе к финальному поле
3. При создании объекта перед созданием потока
4. Когда поток может увидеть объект, он будет обрабатывать
Перевозить
Начиная с Java 1.5, просто напишите тип перечисления, содержащий один элемент:
public enum singleton {exants;}Этот метод функционально похож на метод общественного достояния, но он более краткий и предоставляет механизм сериализации бесплатно, абсолютно предотвращая множественную экземпляру, даже при столкновении с сложной сериализацией или отражением. Хотя этот подход не был широко принят, типы перечисления отдельных элементов стали лучшим способом реализации Singleton.
----------------------------------------------------------------------------------------------------------------------------
1. Каковы детали статического финала
2. Инициализация назначения в статическом поле последовательно и статический блок кода?
3. Как написать синглтонский шаблон для статических внутренних классов
4. Действительно ли примеры в анализе и применении дизайна Java EE действительно эффект ленивого?
Выше всего содержание этой статьи. Я надеюсь, что содержание этой статьи поможет всем, кто учится или работа. Я также надеюсь поддержать Wulin.com больше!