Java: Swing Libraries & Thread Safety

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

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

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

22
задан Ben 11 January 2012 в 03:19
поделиться

11 ответов

  1. Никогда не делают длительные задачи в ответ на кнопку, событие, и т.д. как они находятся на потоке события. При блокировании потока события ВЕСЬ GUI будет абсолютно безразличен получающийся в ДЕЙСТВИТЕЛЬНО очень раздосадованных пользователях. Поэтому Swing кажется медленным и твердым.

  2. Потоки Использования, Исполнители и SwingWorker для выполнения задач НЕ НА EDT (поток отправки события).

  3. не обновляют или создают виджеты за пределами EDT. Примерно единственный вызов, который можно сделать за пределами EDT, является Component.repaint (). Используйте SwingUtilitis.invokeLater, чтобы гарантировать, что определенный код выполняется на EDT.

  4. Использование Методы Отладки EDT и умный стиль (как Вещество , который проверяет на нарушение EDT)

, Если Вы следуете этим правилам, Swing может сделать некоторые очень привлекательные и БЫСТРО РЕАГИРУЮЩИЕ графический интерфейсы пользователя

пример некоторого ДЕЙСТВИТЕЛЬНО потрясающего Swing работа UI: Palantir Technologies .Примечание: Я НЕ работаю на них, просто пример потрясающего колебания. Позор никакая общедоступная демонстрация... Их блог хорош также, редок, но хороший

26
ответ дан basszero 29 November 2019 в 03:51
поделиться

Это - один из тех вопросов, который делает меня довольным, что я купил Robinson & книга Vorobiev по Swing.

Что-либо, что получает доступ к состоянию java.awt.Component, должно быть выполнено в EDT за тремя исключениями: что-либо конкретно зарегистрированное, столь же ориентированное на многопотоковое исполнение, такой как repaint(), revalidate(), и invalidate(); любой Компонент в UI, который еще не был , понял ; и любой Компонент в Апплете прежде, которым назвали Апплет start().

Методы, особенно сделанные ориентированными на многопотоковое исполнение, являются столь редкими, что часто достаточно просто помнить тех, которые являются; можно также обычно сходить с рук предположение, что нет таких методов (совершенно безопасно обернуть вызов перекрашивания в SwingWorker, например).

Реализованный средства, что Компонент является любой контейнером верхнего уровня (как JFrame), на котором любой из setVisible(true), show(), или pack() назвали, или это было добавлено к реализованному Компоненту. Это означает, что прекрасно подходит для создания UI в основном () метод, как много учебных примеров делают, так как они не звонят setVisible(true) на контейнере верхнего уровня, пока каждый Компонент не был добавлен к нему, шрифты и настроенные границы, и т.д.

По подобным причинам, совершенно безопасно создать апплет UI в init() метод, и затем звонить start() после того, как это все создается.

Переносящиеся последующие изменения Компонента в Runnables для отправки к [1 111] становится легким разобраться после выполнения его только несколько раз. Одна вещь, которую я нахожу раздражающими, читает, состояние Компонента (скажите, someTextField.getText()) от другого потока. Технически, это должно быть обернуто в [1 113], также; на практике это может сделать код ужасным быстрый, и я часто не беспокоюсь, или я стараюсь захватить ту информацию в начальное время обработки событий (обычно правильное время, чтобы сделать это в большинстве случаев так или иначе).

11
ответ дан Paul Brinkley 29 November 2019 в 03:51
поделиться

Это не просто, что Swing не ориентирован на многопотоковое исполнение (не, много), но это враждебно к потоку. Если Вы начинаете делать материал Swing на единственном потоке (кроме EDT), то, когда в случаях, где Swing переключается на EDT (не зарегистрированный) могут быть проблемы потокобезопасности. Даже текст Swing, который имеет целью быть ориентированным на многопотоковое исполнение, не полезно ориентирован на многопотоковое исполнение (например, для добавления к документу, сначала необходимо найти длину, которая могла бы измениться перед вставкой).

Так, сделайте все манипуляции Swing на EDT. Обратите внимание, что EDT не является потоком, к основному обращаются, поэтому запустите свои (простые) приложения Swing как этот шаблон:

class MyApp {
    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
            runEDT();
        }});
    }
    private static void runEDT() {
        assert java.awt.EventQueue.isDispatchThread();
        ...
8
ответ дан Tom Hawtin - tackline 29 November 2019 в 03:51
поделиться

Активно постарайтесь не делать любую работу Swing вообще за исключением потока диспетчеризации события. Swing был записан, чтобы быть легким расшириться, и Sun решил, что однопоточная модель была лучше для этого.

у меня не было проблем при следовании моему совету выше. Существуют некоторые обстоятельства, откуда можно 'качаться' других потоков, но я никогда не находил потребность.

3
ответ дан paxdiablo 29 November 2019 в 03:51
поделиться

При использовании Java 6 тогда, SwingWorker является определенно самым легким способом иметь дело с этим.

В основном Вы хотите удостовериться, что что-либо, что изменяет UI, выполняется на EventDispatchThread.

Это может быть найдено при помощи SwingUtilities.isEventDispatchThread () метод, чтобы сказать Вам, если Вы находитесь в нем (обычно не хорошая идея - необходимо знать, какой поток активен).

, Если Вы не находитесь на EDT тогда, Вы используете SwingUtilities.invokeLater () и SwingUtilities.invokeAndWait () для вызова Runnable на EDT.

при обновлении UI не на EDT Вы получаете некоторое невероятно странное поведение. Лично я не считаю это дефектом Swing, Вы получаете некоторую хорошую эффективность, не имея необходимость синхронизировать все потоки для обеспечения обновления UI - просто необходимо помнить тот протест.

2
ответ дан Aidos 29 November 2019 в 03:51
поделиться

'Небезопасная потоком' фраза кажется, что существует что-то по сути плохо (Вы знаете... 'безопасный' - хороший; 'небезопасный' - плохо). Действительность - то, что потокобезопасность прибывает в стоимость - ориентированные на многопотоковое исполнение объекты часто являются путем, более сложным для реализации (и Swing достаточно сложен, как раз когда это.)

кроме того, потокобезопасность достигается или использующий блокирующий (замедляются) или (сложные) стратегии сравнивать-и-подкачивать. Учитывая, что графические интерфейсы с людьми, которые склонны быть непредсказуемыми и трудными синхронизироваться, много инструментариев, решили направить все события через единственный насос события. Это верно для Windows, Swing, SWT, GTK и вероятно других. На самом деле я не знаю единственный инструментарий GUI, который действительно ориентирован на многопотоковое исполнение (подразумевать, что можно управлять внутренним состоянием его объектов от любого потока).

то, Что обычно делается вместо этого, - то, что графический интерфейсы пользователя позволяют справляться с небезопасностью потока. Как другие отметили, Swing всегда обеспечивал несколько упрощенный SwingUtilities.invokeLater (). Java 6 включает превосходный SwingWorker (доступный для предыдущих версий с Swinglabs.org). Существуют также сторонние библиотеки как Фокстрот для управления потоками в контексте Swing.

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

Это тривиально для создания каждого API колебания, чтобы поместить объявление о вакансиях к EDT для каждого набора свойств, делать недействительным, и т.д., который сделал бы его ориентированным на многопотоковое исполнение, но за счет крупного замедления. Можно даже сделать это сами использование AOP. Для сравнения выдает исключения SWT, когда к компоненту получают доступ от неправильного потока.

2
ответ дан 2 revs 29 November 2019 в 03:51
поделиться

Вот шаблон для того, чтобы сделать поток-freindly колебания.

Действие Поддевушки (MyAction) и делает, это - поточный doAction. Заставьте конструктора взять Имя строки.

Дают ему краткий обзор actionImpl () метод.

Позволяют ему быть похожим.. (псевдокод, предупреждающий!)

doAction(){
new Thread(){
   public void run(){
    //kick off thread to do actionImpl().
       actionImpl();
       MyAction.this.interrupt();
   }.start();  // use a worker pool if you care about garbage.
try {
sleep(300);
Go to a busy cursor
sleep(600);
Show a busy dialog(Name) // name comes in handy here
} catch( interrupted exception){
  show normal cursor
}

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

, Если Вы хотите быть действительно хорошими, сделайте сон в другом рабочем потоке также.

1
ответ дан Tim Williscroft 29 November 2019 в 03:51
поделиться

Обратите внимание, что даже образцовые интерфейсы не ориентированы на многопотоковое исполнение. Размер и содержание запрашиваются с отдельным, получают методы и таким образом, нет никакого способа синхронизировать тех.

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

состояние Обновления модели всегда в EDT избегает их.

1
ответ дан iny 29 November 2019 в 03:51
поделиться

invokeLater () и invokeAndWait () действительно ДОЛЖЕН использоваться при выполнении любого взаимодействия с компонентами графического интерфейса пользователя от любого потока, который НЕ является EDT.

Это может работать во время разработки, но как большинство параллельных ошибок, Вы начнете видеть, что странные исключения подходят, которые кажутся абсолютно не связанными, и происходят non-deterministly - обычно определяемый после поставки реальными пользователями. Не хороший.

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

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

1
ответ дан madlep 29 November 2019 в 03:51
поделиться

Для получения дополнительной информации о потоке, Укрощение потоков Java от Аллена Холуба Это старая книга, но она отлично читается.

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

http://www.amazon.com/Taming-Java-Threads-Allen-Holub/dp/1893115100 http: / /www.holub.com/software/taming.java.threads.html

В конце этого раздела найдите раздел «Если бы я был королем».

1
ответ дан 29 November 2019 в 03:51
поделиться

An alternative to using intelligent skins like substance is to create the following utility method:

public final static void checkOnEventDispatchThread() {
    if (!SwingUtilities.isEventDispatchThread()) {
        throw new RuntimeException("This method can only be run on the EDT");
    }
}

Call it in every method you write that is required to be on the event dispatch thread. An advantage of this would be to disable and enable system wide checks very quickly, eg possibly removing this in production.

Note intelligent skins can of course provide additional coverage as well as just this.

4
ответ дан 29 November 2019 в 03:51
поделиться
Другие вопросы по тегам:

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