2009-10-22 2 views
0

Довольно уверен, что все эти подходы будут работать, но я был бы признателен за то, что это лучшее.использование invokeLater

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

01 new Thread(){ 
02 public void run(){ 
03 
04 for (int i = 0; i < 100; i++){ 
05  // some processing 
06  doSomething(); 
07  // update some ui components 
08  panel.doSomeUi(); 
09 } 
10 
11 panel.revalidate(); 
12 panel.repaint(); 
13 
14 }}.start(); 

Какой из следующих трех подходов вы выбрали бы и почему?

  1. обертывание весь код в invokeLater
  2. вызов invokeLater внутри doSomeUi(), а затем снова возобновляют/перекрашивать
  3. использовать только invokeLater для REVALIDATE/перекрашивать в конце

Для шахты:

вариант 1 будет висеть в процессе обработки событий (EPT), в то время как вся обработка происходит

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

вариант 3 был бы наиболее эффективны, но могут иметь некоторые проблемы с обеспечением безопасности потоков.

Желаем услышать другие мнения.

ответ

3

doSomeUi() некоторые из них следует обернутых в invokeLater() и должен запускать любую перерисовку/перерисовку - поток Swing UI будет рисоваться, пока вы продолжаете вычислять.

Накладные расходы на создание большого количества недолговечных Runnable будут крошечными на современной VM и не должны быть проблемой.

Итак, вариант 2 (с предлагаемой модификацией) должен быть им. При написании многопоточного кода медленное и правильное всегда лучше, чем быстро и беспорядочно.

+0

Я приму этот ответ, если кто-то не перейдет немного глубже ... – pstanton

-2

Вы прочитали Java Lesson: Concurrency in Swing и рассмотрите возможность использования рабочих резьб. Также проверьте TumbleItem Example

Урок явно говорит:

Задачи на диспетчеризацию событий нить должны закончить быстро; если они этого не делают, необработанные события резервное копирование, а пользователь интерфейс перестает отвечать.

и

Когда программа Свинг нужно выполнить затянувшийся задачи, как правило, использует один из рабочих потоков

+0

спасибо, но это не сильно изменилось, по сути, вы говорите, что используете утилиту или многие экземпляры класса утилиты, чтобы сделать то же самое ... Я не использовал SwingWorker, потому что он относительно новый , но я понимаю, что это просто класс удобства, чтобы инкапсулировать задачу из двух частей - обработку + ui. правильно? – pstanton

1

Первое, что я получил бы, чтобы оно работало однопоточно. В качестве неотъемлемой части этого я бы удостоверился, что у меня хороший код (например,не распространяются Thread и JPanel), с хорошим разделением «бизнес-логики» и пользовательского интерфейса, тестов и т. д. Это может быть не что-то впечатляющее, но оно может быть доставлено. Проверьте это на управление версиями. Тогда, возможно, посмотрите, есть ли небольшая, горячая секция, которую я могу сделать параллельно.

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

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

Важно отметить, что действия, которые пользовательский интерфейс отправляет в «бизнес-модель» и обновления состояния в обратном направлении, должны быть как можно более развязаны (то есть работать с SwingWorker).

+0

во-первых, когда я упоминал продление JPanel? во-вторых, в то время как ваши советы ** звучат ** хорошо, я не вижу, как это связано с вопросом. я четко заявил, что для аргументов, хорошее разделение невозможно. возможно, это вопрос, который является ошибочным, но то, что я пытаюсь получить, - это скорее компромисс за блокировку EDT для всего процесса, многократное блокирование EDT во время процесса или выполнение большинства задач пользовательского интерфейса с EDT и затем «повторная синхронизация» путем перерисовки/проверки на EDT в конце. – pstanton

+1

'panel.doSomeUi();' * предлагает * расширение 'JPanel' для меня. Возможно, 'doSomeUi' является подставкой для некоторых методов JPanel, но с EDT есть ограниченный выбор. Если разделение «невозможно», как я предлагаю в своем первом абзаце, первый порядок ведения бизнеса состоит в том, чтобы сделать «невозможным». –

+0

ok Я должен был написать doSomeUi (панель); он должен был быть полусудовым кодом, например, который предложил бы код ui в рамках одного контейнера. – pstanton

1

revalidate и repaint is thread safe. У них есть своя собственная функция invokeLater, встроенная в них, вы можете вызвать revalidate и перерисовать из любого потока и в любое время. Даже настолько разумно, что если вы вызовете revalidate тысячу раз, прежде чем он фактически проверит что-либо, он объединит все эти тысячи вызовов в один вызов.

Смежные вопросы