Является ли обновление EDT в разгаре абсолютным правилом или есть исключения?
В Swing графический интерфейс должен обновляться только EDT, поскольку компоненты графического интерфейса не являются поточно-ориентированными.
Мой вопрос заключается в том, что если у меня есть один поток, отличный от EDT, который предназначен для обновления определенного компонента, и этот компонент не доступен ни одному другому потоку в моей программе, только этот отдельный поток, это нормально? В моем случае у меня есть JTable
и поток получает информацию из сети и обновляет таблицу (без использования EventQueue.invokeLater
). Все остальные компоненты обновляются из EDT. До сих пор я не видел проблемы, и мне было интересно, появится ли ошибка в конце концов.
ОБНОВЛЕНИЕ Моя цель состояла в том, чтобы обновить таблицу в режиме реального времени. Данные постоянно поступают из сети, и для этого я выделил 1 поток только для таблицы, чтобы она постоянно обновлялась по мере их поступления. Если я использую SwingUtilities.invokeLater, это означает, что таблица будет обновлена, когда будет доступно EDT. Разве свинг не должен использоваться для требований обновления в реальном времени?
5 ответов
Есть несколько методов, задокументированных как поточно-ориентированные. Я верю немного меньше в JDK7, потому что оказывается, что некоторые из них нереализуемы как поточно-ориентированные. По большей части Swing является враждебным к потоку - его следует использовать из потока AWT EDT. Это в основном потому, что он использует EventQueue.invokeLater
внутренне в "случайном порядке". Также есть скрытое общее состояние (вы можете изменить PL&F без необходимости указывать, например, каждый компонент). Некоторые классы вы можете рассматривать как независимые от потоков, но они не документированы как таковые.
Ответ таков: всегда используйте EDT для Swing. Как и в случае с большинством потоковых ошибок, вам может показаться, что это сходит с рук, а затем внезапно происходит сбой в работе. Эту ошибку, вероятно, будет сложно диагностировать и воспроизвести (особенно если она возникает только в производственных системах на определенных системах). Исправление сильно нарушенной базы кода может быть неинтересным. Держите его в чистоте с самого начала.
Вместо того, чтобы пытаться рассуждать о том, будет ли это работать или нет, я бы просто придерживался известного "правила", заключающегося в том, что вы должны взаимодействовать только с компонентами графического интерфейса, используя поток диспетчеризации событий. Когда вы получаете данные из сети, просто обновите таблицу, используя SwingUtilities.invokeLater
(или же invokeAndWait
).
Вы можете не сразу увидеть проблемы, но вполне возможно, что вы это сделаете в будущем.
Вы должны обновить компоненты графического интерфейса на EDT. Период. (Есть несколько устаревших исключений из этого правила - но они все равно молча перенесли вещи в EDT). EDT работает как насос сообщений (как и большинство оконных систем) - вы должны жить в рамках этого ограничения, если вы хотите обновить компоненты GUI.
Если вы хотите, чтобы ваш стол обновлялся быстро, держите EDT в чистоте - не загружайте его слишком сильно.
Если вы работаете с обновлением живых таблиц, я настоятельно рекомендую вам взглянуть на GlazedLists - у них очень и очень хорошая реализация SwingThreadProxyList, которая заботится об эффективной публикации обновлений в EDT. Вы должны согласиться выпить koolaid GlazedLists, чтобы пойти этим путем, но это очень вкусный koolaid (я люблю GL).
Это абсолютное правило, если вы не хотите гоночных условий. Поток отправки событий достаточно быстр, чтобы экран нашего приложения видеонаблюдения не нуждался во взломах.
Разве Swing не должен использоваться для требований обновления в реальном времени?
Нет. Вы можете обновить модель данных с достаточной скоростью, но графический интерфейс обычно подчинен. Вы можете воспользоваться любой задержкой сети в вашей среде. В качестве альтернативы вам может понадобиться что-то вроде Oracle Sun Real-Time System.
Вы можете улучшить "жизнеспособность" EDT, делая краткие обновления и используя минимальную, правильную синхронизацию. Несколько альтернатив обсуждаются здесь.