Некоторое время назад я прочитал действительно хороший блог, в котором обсуждается эта проблема (упомянутая Карлом Билефельдом), и в основном он говорит о том, что очень опасно пытаться сделать поток комплекта пользовательского интерфейса безопасным, так как он вводит возможные взаимоблокировки и зависит от того, как Реализованы условия гонки в рамках.
Существует также соображение производительности. Не так много сейчас, но когда Swing был впервые выпущен, его сильно критиковали за его производительность (была плохая), но это не было на самом деле виной Swing, это было отсутствие у людей знаний о том, как его использовать.
SWT реализует концепцию безопасности потоков, создавая исключения, если вы нарушаете это, не очень, но, по крайней мере, вы узнали об этом.
Например, если вы посмотрите на процесс рисования, порядок, в котором элементы окрашиваются, очень важен. Вы не хотите, чтобы рисование одного компонента имело побочный эффект на любой другой части экрана. Представьте, что вы могли бы обновить свойство текста метки, но оно было нарисовано двумя разными потоками, что может привести к повреждению вывода. Таким образом, все рисование выполняется в одном потоке, обычно в соответствии с порядком требований / запросов (но иногда сокращается, чтобы уменьшить количество реальных физических циклов рисования)
Вы упомянули о переходе с Swing на JavaFX, но у вас возникла бы эта проблема практически с любой инфраструктурой пользовательского интерфейса (не только с толстыми клиентами, но и с веб-интерфейсом), но Swing, кажется, является той, которая подчеркивает эту проблему.
Вы могли бы разработать промежуточный уровень (контроллер контроллера?), Задачей которого является обеспечение правильной синхронизации вызовов в пользовательском интерфейсе. Невозможно точно знать, как вы могли бы проектировать свои части API, не относящиеся к пользовательскому интерфейсу, с точки зрения API пользовательского интерфейса, и большинство разработчиков будут жаловаться, что любая защита потоков, реализованная в API пользовательского интерфейса, была ограничительной или не отвечала их потребностям. Лучше позволить вам решить, как вы хотите решить эту проблему, исходя из своих потребностей
Одна из самых больших проблем, которую вам необходимо рассмотреть, - это возможность обосновать данный порядок событий на основе известных входных данных. Например, если пользователь изменяет размер окна, модель очереди событий гарантирует, что будет происходить заданный порядок событий, это может показаться простым, но если очередь допускает события, запускаемые другими потоками, вы больше не можете гарантировать порядок в какие события могут произойти (состояние гонки), и внезапно вы должны начать беспокоиться о разных состояниях и ничего не делать, пока не произойдет что-то другое, и вам не придется делиться флагами состояний вокруг, и в итоге вы получите спагетти.
Хорошо, вы могли бы решить эту проблему, имея какую-то очередь, которая упорядочивала события в зависимости от времени их выпуска, но разве это не то, что у нас уже есть? Кроме того, вы все еще не можете гарантировать, что поток B будет генерировать свои события ПОСЛЕ потока A
Основная причина, по которой люди расстраиваются из-за того, что им приходится думать о своем коде, заключается в том, что их заставляют думать о своем коде / дизайне. "Почему это не может быть проще?" Это не может быть проще, потому что это не простая проблема.
Я помню, когда была выпущена PS3, и Sony активно рассказывала о процессоре Cell и о его способности выполнять отдельные строки логики, декодировать аудио, видео, загружать и разрешать данные модели. Один из разработчиков игр спросил: «Это все круто, но как вы синхронизируете потоки?»
Проблема, о которой говорил разработчик, заключалась в том, что в какой-то момент все эти отдельные потоки должны были быть синхронизированы до одного канала для вывода. Бедный ведущий просто пожал плечами, поскольку это была не та проблема, с которой они были знакомы. Очевидно, у них уже есть решения для решения этой проблемы, но в то время это было забавно.
Современные компьютеры принимают много информации одновременно из множества разных мест, все эти данные должны быть обработаны и доставлены пользователю на расстоянии, что не мешает представлению другой информации, поэтому это сложная проблема без единственное простое решение.
Теперь, имея возможность переключать фреймворки, это непросто спроектировать, НО, на мгновение возьмем MVC, MVC может быть многоуровневым, то есть у вас может быть MVC, который непосредственно связан с управлением фреймворком UI, вы затем можно обернуть это, опять же, в MVC более высокого уровня, который имеет дело с взаимодействиями с другими (потенциально многопоточными) структурами, этот уровень будет обязан определять, как нижний уровень MVC уведомляется / обновляется.
Затем вы будете использовать кодирование для сопряжения шаблонов проектирования и шаблонов фабрики или сборщика для создания этих различных слоев. Это означает, что многопоточные фреймворки будут отделены от уровня пользовательского интерфейса за счет использования среднего уровня в качестве идеи.