Использование нескольких потоков в Java-программе и необходимость создания объектов Swing в EDT - PullRequest
2 голосов
/ 01 февраля 2011

Re: Требование для создания объекта Swing в потоке диспетчеризации событий.

Я работаю над приложением, целью которого является мониторинг и отображение состояния различных удаленных встроенных серверов.Я довольно новичок в Java, и мое понимание требований относительно объектов Swing и EDT неполно.

Основной графический интерфейс пользователя запускается на EDT обычным образом следующим образом:

    javax.swing.SwingUtilities.invokeLater(new Runnable() {

        public void run() {
            createAndShowGUI();
        }
    });

Пользователь может затем выбрать один или несколько пунктов меню, соответствующих той или иной удаленной машине.Результатом этого является создание нового потока каждый раз следующим образом:

                new Thread(new VoterStatus(itemNumber)).start();

, который вызывает метод "run" класса VoterStatus, который, в свою очередь, создает новое окно с JFrame.Новый поток, экземпляр класса VoterStatus, затем опрашивает (TCP и т. Д.) Указанный конкретный удаленный (itemNumber), собирая различные биты информации и отображая их в JFrame.

Таких потоков может быть любое количествосоответствующие экземпляру VoterStatus, все обновляют свои собственные окна.Нет разделения данных между этими различными окнами / JFrame / задачами.

Кажется, это работает нормально, но безопасно ли?

Нарушил ли я правило о создании компонентов Swing в EDT?

Будет ли полезным использование класса SwingWorker?

Буду признателен за любые комментарии более опытных Java-программистов.в таких вопросах.

Спасибо, Стив

Ответы [ 4 ]

5 голосов
/ 01 февраля 2011

Из раздела учебника по Swing под названием Тема отправки событий

Некоторые методы компонента Swing помечены как «потокобезопасные» в спецификации API; их можно безопасно вызывать из любого потока. Все остальные методы компонента Swing должны вызываться из потока диспетчеризации событий. Программы, которые игнорируют это правило, могут работать правильно большую часть времени, но подвержены непредсказуемым ошибкам, которые трудно воспроизвести.

Я всегда вызываю свои методы на EDT, чтобы не тратить время на погоню за гремлинами.

Edit:

Я только что прочитал другую публикацию, в которой говорится, что комментарий "потокобезопасный" был удален из многих методов в API JDK7. http://forums.oracle.com/forums/thread.jspa?threadID=2167051. Это выглядит как еще одна причина для того, чтобы убедиться, что все методы, которые влияют на GUI, выполняются в EDT.

2 голосов
/ 01 февраля 2011

@ camickr имеет на это право.Неправильно синхронизированные программы могут появляться для работы большую часть времени, но результат не является надежным.Несколько связанных подходов обсуждаются здесь .SwingWorker является особенно удобной реализацией интерфейса Future, поскольку process() выполняется в потоке диспетчеризации событий.

0 голосов
/ 02 февраля 2011

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

Рогаш прокомментировал, что если бы я только создавал GUI на EDT, я был бы в порядке, но это не совсем соответствует строгой интерпретации правила?

Дополнительные потоки создаются в EDT, но они по-прежнему являются отдельными потоками.

Хотя может быть желательным несколько лучшее разделение графического интерфейса пользователя и интерфейса связи, я ожидаю, что это значительно усложнит основной код графического интерфейса пользователя, поскольку ему придется определить, из какого окна возникли различные события, а затем обновить правильное окно, не говоря уже связь между различными потоками и основным потоком GUI. Возможно, я преувеличиваю эту трудность (я еще не придумал и не задумывался над тем, как ее кодировать), но она может показаться более сложной. Каждый из потоков / JFrame уже имеет несколько массивов JToggleButton (30 элементов), вызывающих потенциальные события, и около 10 массивов JTextField с тем же числом элементов, требующих обновления.

Конечно, если мой метод небезопасен, мне придется его изменить, и это все!

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

Еще раз спасибо Стив

PS Я пытался зарегистрироваться на этом форуме, но я думаю, что это обсуждение останется с моей незарегистрированной персоной.

0 голосов
/ 01 февраля 2011

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

Однако я бы предложил другой подход. Вместо того, чтобы запускать новый Thread, который создает окна и прочее для каждого нового VoterStatus, создайте компоненты пользовательского интерфейса в EDT в ответ на ActionEvents из меню или чего-либо еще, и выполняйте обработку сетевого содержимого только в другая нить. Затем получите результаты и используйте EDT для их отображения. Как вы предположили, SwingWorker идеально подходит для этого - это именно тот вид использования, для которого он был разработан. Для меня это более чистое разделение, максимально отделяющее пользовательский интерфейс от сетевого.

...