Как “это” выходит из конструктора в Java?

Как MrTelly заявил, DispatcherTimer является способом сделать это. Это тесно интегрируется с очередью Диспетчера и удостоверяется, что Ваши обратные вызовы находятся на корректном потоке. Ниже некоторые хорошие статьи об этом классе. Некоторый пример кода ниже детализации основного примера:

//  DispatcherTimer setup
DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0,0,1);
dispatcherTimer.Start();

private void dispatcherTimer_Tick(object sender, EventArgs e)
{
    // Updating the Label which displays the current second
    lblSeconds.Content = DateTime.Now.Second;

    // Forcing the CommandManager to raise the RequerySuggested event
    CommandManager.InvalidateRequerySuggested();
}

Таймер по сравнению с документацией DispatcherTimer

MSDN

20
задан non sequitor 19 October 2009 в 12:30
поделиться

5 ответов

Действительно простой пример:

public class Test
{
    private static Test lastCreatedInstance;

    public Test()
    {
        lastCreatedInstance = this;
    }
}
17
ответ дан 29 November 2019 в 23:04
поделиться

Стив Гилхэм прав в своей оценке того, почему блокировка с двойной проверкой нарушена. Если поток A входит в этот метод, а obj имеет значение null, этот поток начнет создавать экземпляр объекта и назначать ему obj. Поток B, возможно, может войти, пока поток A все еще создает экземпляр этого объекта (но не завершает), а затем будет рассматривать объект как не нулевой, но поле этого объекта, возможно, не было инициализировано. Частично сконструированный объект.

Однако тот же тип проблемы может возникнуть, если вы позволите ключевому слову this избежать конструктора. Допустим, ваш конструктор создает экземпляр объекта, который разветвляет поток, и этот объект принимает ваш тип объекта. Теперь ваш объект может быть не полностью инициализирован, то есть некоторые из ваших полей могут быть нулевыми. Ссылка на ваш объект тем, что вы создали в своем конструкторе, теперь может ссылаться на вас как на ненулевой объект, но получать нулевые значения полей.

Еще немного пояснения:

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

2
ответ дан 29 November 2019 в 23:04
поделиться

Пример: в конструкторе вы создаете слушатель событий внутренний класс (он имеет неявную ссылку на текущий объект) и регистрируете его в списке слушателей.
=> Таким образом, ваш объект может использоваться другим потоком, даже если он не завершил выполнение своего конструктора.

     public class A {

      private boolean isIt;
      private String yesItIs;

      public A() {
        EventListener el = new EventListener() { ....};
        StaticListeners.register(el);
        isIt = true;
        yesItIs = "yesItIs";
      }
     }

Дополнительная проблема, которая может возникнуть позже: объект A может быть полностью создан, доступен для всех потоков, может использоваться другим thread ... за исключением того, что этот поток мог видеть экземпляр A как созданный, yesItIs с его значением «yesItIs», но не isIt ! Вы не поверите, но такое могло случиться! Что происходит:

=> синхронизация только наполовину касается блокировки потока, другая половина касается видимости между потоками .

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

24
ответ дан 29 November 2019 в 23:04
поделиться

Это причина, по которой двойная проверка блокировки не работает. Наивный код

if(obj == null)
{
  synchronized(something)
  {
     if (obj == null) obj = BuildObject(...);
  }
} 
// do something with obj

небезопасен, потому что присвоение локальной переменной может произойти до остальной конструкции (конструктор или фабричный метод). Таким образом, поток 1 может находиться на этапе BuildObject , когда поток 2 входит в тот же блок, обнаруживает ненулевой obj и затем переходит к работе с неполным объектом (поток 1, имеющий было запланировано в середине разговора).

7
ответ дан 29 November 2019 в 23:04
поделиться
public class MyClass{
    String name;    

    public MyClass(String s)
    {
        if(s==null)
        {
            throw new IllegalArgumentException();
        }
        OtherClass.method(this);
        name= s;
    }

    public getName(){ return name; }
}

В приведенном выше коде OtherClass.method () передается экземпляр MyClass , который на данный момент построен не полностью, т.е. еще не выполняется договор о том, что свойство name не равно нулю.

5
ответ дан 29 November 2019 в 23:04
поделиться
Другие вопросы по тегам:

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