Может ли этот Java-синглтон многократно перестраиваться в WebSphere 6?

В Java, когда оператор «==» используется для сравнения двух объектов, он проверяет, ссылаются ли объекты на одно и то же место в памяти. Другими словами, он проверяет, являются ли имена двух объектов в основном ссылками на одно и то же место в памяти.

Класс Java String фактически переопределяет реализацию equals () по умолчанию в классе Object и переопределяет этот метод, чтобы он проверял только значения строк, а не их местоположения в памяти. Это означает, что если вы вызываете метод equals () для сравнения двух объектов String, то, пока действительная последовательность символов равна, оба объекта считаются равными.

Оператор == проверяет, являются ли две строки точно одним и тем же объектом.

Метод .equals() проверяет, имеют ли две строки одно и то же значение.

13
задан Erick Robertson 1 December 2011 в 13:02
поделиться

10 ответов

Я нашел это на сайте Sun:

Несколько Одиночных элементов, Одновременно Загруженных Различными Загрузчиками Класса

, Когда два загрузчика класса загружают класс, у Вас на самом деле есть две копии класса, и у каждого может быть его собственный экземпляр Singleton. Это особенно релевантно в сервлетах, работающих в определенных механизмах сервлета (iPlanet, например), где каждый сервлет значением по умолчанию использует свой собственный загрузчик класса. Два различных сервлета, получающие доступ к совместной Singleton, на самом деле, получат два различных объекта.

Несколько загрузчиков класса происходят чаще всего, чем Вы могли бы думать. Когда браузеры загружают классы из сети для использования апплетами, они используют отдельный загрузчик класса для каждого адреса сервера. Точно так же Jini и системы RMI могут использовать отдельный загрузчик класса для различных кодовых баз, с которых они загружают файлы класса. Если Ваша собственная система использует пользовательские загрузчики класса, все одинаковые, проблемы могут возникнуть.

, Если загружено различными загрузчиками класса, два класса с тем же именем, даже то же имя пакета, рассматривают как отличные - даже если на самом деле они - байт для байта тот же класс. Различные загрузчики класса представляют различные пространства имен, которые отличают классы (даже при том, что имена классов являются тем же), так, чтобы два MySingleton классы были на самом деле отличны. (См. "Загрузчики класса как Механизм Пространства имен" в Ресурсах.), Так как два объекта Singleton принадлежат двум классам того же имени, будет казаться на первый взгляд, что существует два объекта Singleton того же класса.

Цитата .

В дополнение к вышеупомянутой проблеме, если firstTime() не синхронизируется, у Вас могли бы быть проблемы поточной обработки там также.

16
ответ дан palacsint 1 December 2011 в 13:02
поделиться
  • 1
    Нет, это не взаимодействует с BIOS всегда, он только использует ЦП. Этот код запрашивает ЦП непосредственно для it' s спецификации, подобные чтению it' s порядковый номер. Я добавлю пару комментариев к коду позже сегодня. – Sergey L. 3 October 2012 в 09:44

Нет это не будет создано много раз. Это статично, таким образом, это будет только создано однажды, право, когда класс будет затронут впервые Classloader.

Только исключение - если у Вас, оказывается, есть несколько Classloaders.

(от GeekAndPoke):

alt text

13
ответ дан Epaga 1 December 2011 в 13:02
поделиться
  • 1
    Как обещано я прокомментировал свой код и добавил некоторый более информативный вывод. – Sergey L. 3 October 2012 в 13:21

Как другие упомянули, статический инициализатор будет только выполнен однажды на classloader.

Одна вещь, на которую я смотрел бы, firstTime() метод - почему не может работа в doPreparations() быть обработанным в самом одиночном элементе?

Походит на противный набор зависимостей.

5
ответ дан matt b 1 December 2011 в 13:02
поделиться
  • 1
    Я попробовал это, но я замечаю, что как ArraySize увеличивается, время - также. Вероятно, потому что, если Шаг является постоянным, количество увеличений внутреннего цикла, поскольку ArraySize увеличивается. Кроме того, я обновил свой вопрос... см. ОБНОВЛЕНИЕ (Попытка) – Jiew Meng 26 September 2012 в 10:27

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

, Который сказал, JVM не гарантирует, что Ваш класс будет загружен только однажды. Однако, даже если это будет загружено несколько раз, Ваше веб-приложение будет все еще видеть только соответствующий одиночный элемент, поскольку это будет загружено или в веб-приложении classloader или в его родителе. Если у Вас будет несколько развернутых веб-приложений, то в первый раз () будет назван однажды для каждого приложения.

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

5
ответ дан Jevgeni Kabanov 1 December 2011 в 13:02
поделиться
  • 1
    Первое свойство является размером строки кэша (например, 64B), если шаг будет меньше тогда 64B, то Вы получите удачное обращение в кэш, по крайней мере, каждый второй доступ. Тогда мы хотим видеть размер кэша L1 (например, 64 КБ), таким образом, здесь мы должны посмотреть на число шагов для каждого внутреннего цикла. Так позволяет, говорят, что у нас есть 1024K ArraySize и Stride=128B тогда, количество внутренних циклов: 16384. С известным размером строки кэша мы знаем, что это возьмет 512K для хранения и не поместится в кэш L1. Помните размер строки и LRU. – user1443778 27 September 2012 в 02:13

Единственная вещь, которую я изменил бы о той реализации Singleton (кроме не использования Singleton вообще) состоит в том, чтобы сделать финал поля экземпляра. Статическое поле будет инициализировано однажды на загрузке класса. Так как классы загружаются лениво, Вы эффективно получаете ленивое инстанцирование бесплатно.

, Конечно, если это загружается из отдельных загрузчиков класса, Вы получаете несколько "одиночных элементов", но это - ограничение каждой одноэлементной идиомы в Java.

РЕДАКТИРОВАНИЕ : новые () и doPreparations () биты действительно смотрят подозреваемый все же. Разве они не могут быть перемещены в конструктора одноэлементного экземпляра?

2
ответ дан Dan Dyer 1 December 2011 в 13:02
поделиться
  • 1
    Им не разрешают использовать системную информацию о конфигурации для этого присвоения, и sysconf не дает Вам информацию о кэше в прошлый раз, когда я проверил. – Sergey L. 5 October 2012 в 10:29

Это станет только загруженным однажды, когда класс будет загружен classloader. Этот пример обеспечивает лучшую реализацию Singleton однако, он максимально лениво загружается и ориентированный на многопотоковое исполнение. Кроме того, это работает во всех известных версиях Java. Это решение является самым портативным через различные компиляторы Java и виртуальные машины.


public class Single {

private static class SingleHolder {
   private static final Single INSTANCE = new Single();
}

private Single() {
...load properties...
}

public static Single getInstance() {
    return SingleHolder.INSTANCE;
}

}

на внутренний класс ссылаются не ранее (и поэтому загрузился не ранее загрузчиком класса), чем момент, которым называют getInstance (). Таким образом это решение ориентировано на многопотоковое исполнение, не требуя специальных конструкций языка (т.е. энергозависимый и/или синхронизируемый).

0
ответ дан nkr1pt 1 December 2011 в 13:02
поделиться
  • 1
    @JonnyBest Это - только решение, при отсутствии ошибок компилятора после изменения... – habakuk 24 October 2013 в 11:43

Нет - статическая инициализация эти instance будет только когда-либо делаться однажды. Две вещи рассмотреть:

  • Это не ориентировано на многопотоковое исполнение (экземпляр не "публикуется" к оперативной памяти)
  • Ваш firstTime, метод, вероятно, называют многократно, если правильно не синхронизируется
1
ответ дан oxbow_lakes 1 December 2011 в 13:02
поделиться
  • 1
    Это делает. Назовите его с _SC_LEVEL(1_I|1_D|2_|3_|4_)CACHE_(SIZE | ASSOC | LINESIZE).Править: Поэтому я включал включать-файлы, где эти значения определяются. – Mark 8 October 2012 в 09:07

В теории это будет создано только однажды. Однако этот шаблон прерывает различные серверы приложений, где можно получить несколько экземпляров 'одноэлементных' классов (так как они не ориентированы на многопотоковое исполнение).

кроме того, шаблон "одиночка" был critized много. Посмотрите, например Singleton, я люблю Вас, но Вы приносите мне вниз

1
ответ дан Einar 1 December 2011 в 13:02
поделиться
  • 1
    Это решило проблему для меня и должно быть решением! – Jonny Best 22 June 2013 в 17:48

Нет, Это не создаст несколько копий 'Единственных'. (Проблему Classloader посетят позже)

реализация, которую Вы обрисовали в общих чертах, описан как 'Нетерпеливая Инициализация' в книге Briant Goetz -' Параллелизм Java на практике '.

public class Single
{
    private static Single theInstance = new Single();

    private Single() 
    { 
        // load properties
    }

    public static Single getInstance() 
    {
        return theInstance;
    }
}

Однако код не Вы требуемый. Ваш код пытается выполнить ленивую инициализацию после того, как экземпляр будет создан. Это требует, чтобы вся клиентская библиотека работала 'в первый раз ()/doPreparation ()' перед использованием его. Вы собираетесь полагаться на клиент, чтобы сделать правильную вещь, которые делают код очень хрупким.

можно изменить код как следующее, таким образом, не будет никакого дублирующего кода.

public class Single
{
    private static Single theInstance = new Single();

    private Single() 
    { 
        // load properties
    }

    public static Single getInstance() 
    {   
        // check for initialization of theInstance
        if ( theInstance.firstTime() )
           theInstance.doPreparation();

        return theInstance;
    }
}

, К сожалению, это - плохая реализация ленивой инициализации, и это не будет работать в параллельной среде (как контейнер J2EE).

существует много статей, написанных об инициализации Singleton, конкретно на модели памяти. JSR 133 обратился ко многим слабость в модели памяти Java в Java 1.5 и 1.6.

С Java 1.5 & 1.6, у Вас есть несколько вариантов, и они упоминаются в книге' Эффективный Java' Joshua Bloch.

  1. Нетерпеливый Initialziation, как вышеупомянутое [Объект EJ 3]
  2. Ленивая Идиома Класса Держателя Initalization [Объект EJ 71]
  3. Перечислимый Тип [Объект EJ 3]
  4. Проверенная дважды Блокировка с 'энергозависимым' статическим полем [Объект EJ 71]

Решение 3 и 4 будет только работать в Java 1.5 и выше. Таким образом, лучшим решением был бы № 2.

, Вот psuedo-реализация.

public class Single
{
    private static class SingleHolder
    {
        public static Single theInstance = new Single();
    }

    private Single() 
    { 
        // load properties
        doPreparation();
    }

    public static Single getInstance() 
    {
        return SingleHolder.theInstance;
    }
}

Уведомление, которое 'doPreparation ()' является в конструкторе, таким образом, Вы - гарантия для получения правильно инициализированного экземпляра. Кроме того, Вы - piggying назад на ленивой загрузке класса JVM и не нуждаетесь ни в какой синхронизации 'getInstance ()'.

Одна вещь Вы заметили, что статическое поле theInstance не 'окончательное'. пример на Параллелизме Java не имеет 'финала', но EJ делает. Возможно, James может добавить больше цвета к своему ответу на 'classloader' и требовании 'финала' для гарантии правильности,

Однако существует побочный эффект это с использованием 'статического финала'. Компилятор Java очень агрессивен, когда он видит 'статический финал' и пытается встроить его как можно больше. Это упоминается на [1 110] сообщение в блоге Jeremy Manson .

Вот простой пример.

файл: файл A.java

public class A
{
    final static String word = "Hello World";
}

: B.java

public class B
{
    public static void main(String[] args) {
        System.out.println(A.word);
    }
}

после компиляции и A.java и B.java Вы изменяете A.java на следующее.

файл: A.java

public class A
{
    final static String word = "Goodbye World";
}

Вы перекомпилировали 'A.java' и повторно выполняете B.class. Вывод, который Вы получили бы,

Hello World

Что касается проблемы classloader, ответ да, у Вас может быть больше чем один экземпляр Singleton в нескольких classloaders. Можно найти больше информации о [1 111] Википедия . Существует также определенная статья о [1 112] Websphere.

5
ответ дан mjlee 1 December 2011 в 13:02
поделиться
  • 1
    Важно, чтобы Вы на самом деле много раз выполняли внешний цикл (миллионы времен!!!!) и получают среднее время для каждого цикла. Мы интересуемся свойствами в пределе не переходный процесс запуска программы и т.д. – user1443778 27 September 2012 в 02:16

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

В коде ниже вы можете увидеть, как он создается только один раз (при первом вызове конструктора)

дата пакета;

import java.util.Date;

открытый класс USDateFactory реализует DateFactory { частный статический USDateFactory usdatefactory = null;

private USDateFactory () { }

public static USDateFactory getUsdatefactory() {
    if(usdatefactory==null) {
        usdatefactory = new USDateFactory();
    }
    return usdatefactory;
}

public String getTextDate (Date date) {
    return null;
}

public NumericalDate getNumericalDate (Date date) {
    return null;
}

}

0
ответ дан 1 December 2019 в 17:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: