Как поток Java синхронизируется с invokeLater ()? - PullRequest
2 голосов
/ 03 августа 2011

У меня есть поток без графического интерфейса, который запускает JFrame, используя

java.awt.EventQueue.invokeLater(new Runnable() {

    public void run() {
        cardReadPunchGUI = new IBM1622GUI();  // instantiate
        cardReadPunchGUI.setVisible(true);
    }
});

Часть конструктора IBM1622GUI создает для себя "модель", к которой мой поток без графического интерфейса требует доступа:

cardReadPunch = IBM1622GUI.getModel();

Как правильно синхронизировать мой поток без графического интерфейса с новым графическим интерфейсом, который был «вызван позже»?(Без синхронизации, конечно, IBM1622GUI.getModel() просто возвращает ноль.)

Ответы [ 4 ]

4 голосов
/ 03 августа 2011

Используйте

javax.swing.SwingUtilities.invokeAndWait(Runnable doRun);

вместо.

Заставляет doRun.run () выполняться синхронно в событии AWT диспетчерская нить. Этот вызов блокируется, пока все ожидающие события AWT не будут был обработан и (затем) doRun.run () возвращает.

2 голосов
/ 03 августа 2011

Что ж, если у вас есть доступ к нему, вы всегда можете переместить эту конкретную логику за пределы потока Swing и на поток, который вызывает invokeLater.Нет ничего небезопасного в том, что вы делаете там, вне потока Swing, при условии, что конструктор для IBM622GUI ведет себя хорошо.

Кроме этого, вы можете использовать различные другие механизмы.

  1. Вы можете использовать invokeAndWait, так как cgull побеждает меня, сказав.
  2. Вы можете установить для runnable значение Future вместо прямой ссылки и блокировать на главнойвызовите метод будущего get.
  3. У вас может быть CountDownLatch со начальным счетом 1, который вы await() в своем основном потоке, и countDown() из потока Swing.

Существует множество утилит, помогающих с синхронизацией.

2 голосов
/ 03 августа 2011

Id предлагает вам совместно использовать CountDownLatch , инициализированный в 1, как с потоками не-GUI, так и с потоками GUI.

Поток без GUI при запуске вызовет latch.await(), что переведет его в заблокированное состояние.

Поток GUI вызовет latch.countDown(), когда завершит свою инициализацию, после чего не-GUI-поток выйдет из вызова await, и оба потока синхронизируются.

1 голос
/ 03 августа 2011

Обычно вы передаете параметры в поток.Запустите логику в фоновом режиме.А затем отправьте обратно любые изменения, которые вам нужно сделать, для любого из этих объектов или элементов пользовательского интерфейса в потоке пользовательского интерфейса, используя SwingUtilities.invokeLater ().Обычно я создаю простую утилиту, которая позволяет мне указать, что должно выполняться в фоновом потоке, а что - в потоке пользовательского интерфейса.SwingWorker - это то, что вы можете использовать, хотя я нахожу это чрезвычайно болезненным в использовании.Нечто простое, подобное этому:

new AsyncThread<Param,T>() {
   public T executeInBackground( Param param ) {
      // do something long running
      T result = // do something long running;
      return T;
   }

   public void executeOnUI( T result ) {
      // update the UI here, or modify the model, etc.
   }
}.execute( param );

AsyncThread будет выполнять метод executeInBackground () в другом потоке.Затем внутренне он будет отправлять обратно в поток пользовательского интерфейса, используя SwingUtilities.invokeLater ().Затем executeOnUI будет выполняться в потоке пользовательского интерфейса.Метод execute () может создать поток для выполнения в фоновом режиме, обработки исключений и т. Д.

Я бы позволил графическому интерфейсу, возможно, запустить поток, и позволил бы графическому интерфейсу передать его модель или любую часть, которая ему нужна, в тему.А не наоборот.Таким образом, пользовательский интерфейс может дать отзыв о том фоновом потоке, который работает.Но вы не можете позволить фоновому потоку касаться (записывать / изменять / изменять) членов этой модели, которые поток пользовательского интерфейса будет также читать / записывать одновременно.Поэтому, если вы планируете изменить модель в ответ на фоновый поток, опубликуйте ее обратно в поток пользовательского интерфейса, чтобы быть в безопасности.

...