Несовместимые идентификаторы EventQueue

У меня возникла проблема со следующим примером кода, который показывает противоречивое поведение для EventQueue:

public static void main( String[] args ) throws InvocationTargetException, InterruptedException {

    final long[] id1 = new long[ 1 ];
    final long[] id2 = new long[ 1 ];

    EventQueue.invokeAndWait( new Runnable() {
      @Override public void run() {
        id1[ 0 ] = Thread.currentThread().getId();
      }
    } );

    Thread.sleep( 5000 );

    EventQueue.invokeAndWait( new Runnable() {
      @Override public void run() {
        id2[ 0 ] = Thread.currentThread().getId();
      }
    } );

    System.out.println( "id1 = " + id1[0] );
    System.out.println( "id2 = " + id2[0] );

    if(id1[0]!=id2[0]){
      System.out.println("These ID's don't match, even though they were retrieved from the same thread.");
    }

  }

По сути, он получает идентификатор потока очереди событий, ждет 5 секунд, а затем снова получает идентификатор.

По какой-то причине идентификаторы не совпадают. Судя по всему, EventQueue была уничтожена и создана заново. Это нормальное поведение? Это где-то задокументировано? Это ошибка? Даже если это был другой экземпляр, разве у него не должен быть тот же идентификатор?

Если я не выполню Thread.sleep, идентификаторы совпадут.

Мой другой вопрос: как я могу обойти это? Я использую объект, к которому можно получить доступ только в потоке создания. Если это очередь событий (что не обязательно должно быть), я должен иметь возможность проверить, является ли она все еще очередью событий.


person Tovi7    schedule 25.08.2011    source источник


Ответы (1)


Этот поток отправки событий AWT может быть закрыт, когда он больше не нужен (эта страница описывает как спецификацию, так и поведение фактической реализации в JDK 7).

Похоже, здесь происходит следующее: вы используете систему EventQueue для обработки одного события. Тогда это больше не нужно (никаких компонентов AWT/Swing, ...). Через какое-то время отключается.

Затем, когда вы снова используете EventQueue, запускается другой поток, который берет на себя эту роль.

Итак, здесь происходит то, что ваши Runnable.run() методы действительно выполняются в двух разных потоках. Оба потока являются "потоком отправки событий AWT", просто в разное время жизненного цикла JVM.

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

person Joachim Sauer    schedule 25.08.2011
comment
Спасибо. Я надеялся, что будет лучший способ, чем специальная проверка для самого потока EventQueue, но я думаю, что если мне нужно, я должен. :) - person Tovi7; 25.08.2011
comment
Что ж, я бы сказал, что это особый случай в вашем требовании, поскольку вы хотите обрабатывать два разных потока событий так, как если бы они были одинаковыми. Если вы действительно хотите разрешить доступ к чему-либо только одному и тому же потоку, то будет достаточно оставить эту проверку и проверить только идентификатор потока. - person Joachim Sauer; 25.08.2011