Há algum tempo, li um blog muito bom que discute esse problema (mencionado por Karl Bielefeldt), o que basicamente diz é que é muito perigoso tentar tornar o thread do kit de interface do usuário seguro, pois apresenta possíveis bloqueios e depende de como implementadas, condições de corrida no quadro.
Há também uma consideração de desempenho. Agora não muito, mas quando o Swing foi lançado, ele foi fortemente criticado por seu desempenho (ruim), mas isso não foi culpa do Swing, era falta de conhecimento das pessoas sobre como usá-lo.
O SWT aplica o conceito de segurança de encadeamento lançando exceções se você violá-lo, não é bonito, mas pelo menos você está ciente disso.
Se você observar o processo de pintura, por exemplo, a ordem na qual os elementos são pintados é muito importante. Você não deseja que a pintura de um componente tenha efeito colateral em qualquer outra parte da tela. Imagine se você pudesse atualizar a propriedade de texto de uma etiqueta, mas ela fosse pintada por dois segmentos diferentes, e você poderia acabar com uma saída corrompida. Portanto, toda a pintura é feita em um único encadeamento, normalmente com base na ordem de requisitos / solicitações (mas às vezes condensada para reduzir o número de ciclos físicos reais de pintura)
Você mencionou a mudança do Swing para o JavaFX, mas você teria esse problema com praticamente qualquer estrutura de interface do usuário (não apenas com clientes grossos, mas também com a Web). O Swing parece ser o que destaca o problema.
Você pode projetar uma camada intermediária (um controlador de um controlador?), Cuja tarefa é garantir que as chamadas para a interface do usuário sejam sincronizadas corretamente. É impossível saber exatamente como você pode projetar partes da API que não são da interface do usuário da perspectiva da API da interface do usuário e a maioria dos desenvolvedores reclamaria que qualquer proteção de thread implementada na API da interface do usuário era restritiva ou não atendia às suas necessidades. Melhor permitir que você decida como deseja resolver esse problema, com base em suas necessidades
Um dos maiores problemas que você precisa considerar é a capacidade de justificar uma determinada ordem de eventos, com base em informações conhecidas. Por exemplo, se o usuário redimensionar a janela, o modelo da Fila de Eventos garante que uma determinada ordem de eventos ocorrerá, isso pode parecer simples, mas se a fila permitir que eventos sejam acionados por outros encadeamentos, você não poderá mais garantir a ordem em em que os eventos podem ocorrer (uma condição de corrida) e, de repente, você precisa começar a se preocupar com diferentes estados e não fazer nada até que algo mais aconteça. Você começa a compartilhar bandeiras do estado e acaba com espaguete.
Ok, você pode resolver isso tendo algum tipo de fila que ordenou os eventos com base no horário em que foram emitidos, mas não é isso que já temos? Além disso, você ainda não pode garantir que o segmento B gere seus eventos DEPOIS do segmento A
A principal razão pela qual as pessoas ficam chateadas por ter que pensar em seu código é porque elas são feitas para pensar em seu código / design. "Por que não pode ser mais simples?" Não pode ser mais simples, porque não é um problema simples.
Lembro-me de quando o PS3 foi lançado e a Sony estava conversando com o processador Cell e sua capacidade de executar linhas separadas de lógica, decodificar áudio, vídeo, carregar e resolver dados do modelo. Um desenvolvedor de jogos perguntou: "Isso é incrível, mas como você sincroniza os fluxos?"
O problema de que o desenvolvedor estava falando era que, em algum momento, todos esses fluxos separados precisariam ser sincronizados em um único canal para saída. O pobre apresentador simplesmente deu de ombros, pois não era um problema que eles estavam familiarizados. Obviamente, eles tiveram soluções para resolver esse problema agora, mas ele tem graça na época.
Os computadores modernos estão recebendo muitas informações de vários lugares simultaneamente, todas essas informações precisam ser processadas e entregues ao usuário imediatamente, o que não interfere na apresentação de outras informações, por isso é um problema complexo, sem uma única solução simples.
Agora, tendo a capacidade de alternar estruturas, não é uma coisa fácil de projetar, mas, tome MVC por um momento, o MVC pode ser de várias camadas, ou seja, você pode ter um MVC que lida diretamente com o gerenciamento da estrutura da interface do usuário. poderia então envolver isso, novamente, em um MVC de camada superior que lida com interações com outras estruturas (potencialmente multiencadeadas), seria responsabilidade dessa camada determinar como a camada MVC inferior é notificada / atualizada.
Você usaria a codificação para fazer interface com padrões de design e padrões de fábrica ou construtor para construir essas diferentes camadas. Isso significa que as estruturas multithread são dissociadas da camada da interface do usuário através do uso de uma camada intermediária, como uma idéia.