Thread principale vs thread UI in Java

In molti snippet Swing qui indicati come risposte, c’è una chiamata a SwingUtilities#invokeLater dal metodo main :

 public class MyOneClassUiApp { private constructUi() { // Some Ui related Code } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new MyOneClassUiApp().constructUi(); } }); } } 

Ma secondo l’ articolo Threads and Swing , è sicuro build l’interfaccia utente dal thread principale:

Alcuni metodi sono thread-safe: nella documentazione dell’API Swing, i metodi thread-safe sono contrassegnati con questo testo:

Questo metodo è thread-safe, sebbene la maggior parte dei metodi Swing non lo siano.

La GUI di un’applicazione può essere spesso costruita e mostrata nel thread principale: Il seguente codice tipico è sicuro, purché non siano stati realizzati componenti (Swing o altro):

 public class MyApplication { public static void main(String[] args) { JFrame f = new JFrame("Labels"); // Add components to // the frame here... f.pack(); f.show(); // Don't do any more GUI work here... } } 

Quindi, esiste una vera ragione per la costruzione dell’interfaccia utente principale tramite SwingUtilities#invokeLater , oppure questa è solo un’abitudine, da ricordare, negli altri casi?

La regola del thread singolo di Swing: i componenti ei modelli di Swing devono essere creati, modificati e interrogati solo dal thread di invio eventi.” – Concurrency in Practice Java , anche discusso qui e qui . Se non si segue questa regola, non è ansible build, modificare o interrogare in modo affidabile qualsiasi componente o modello che si presume abbia seguito la regola. Un programma può sembrare funzionare correttamente, solo per fallire misteriosamente in un ambiente diverso.

È sicuro creare l’interfaccia utente Swing nel metodo principale, in che modo verranno visualizzati altri componenti prima di configurare l’interfaccia utente? Finché non hai gettato alcune cose sullo schermo, starai bene. In altre parole, questo sarebbe male:

 public class MyApplication { public static void main(String[] args) { JFrame f = new JFrame("Labels"); // Add components to // the frame here... f.pack(); f.show(); // now make another frame: JFrame f2 = new JFrame("Labels2"); // Add components to the 2nd frame here... f2.pack(); f2.show(); } } 

Se hai fatto quanto sopra, avresti JFrame f attivo e funzionante, quindi dovresti aggiungere componenti Swing UI fuori dal thread di invio eventi (EDT). invokeLater esegue il codice invokeLater : non ti farà male usarlo se vuoi maggiore tranquillità.

Penso che usare SwingUtiltities.invokeLater() sia solo un modo più semplice per eseguire codice in modo asincrono. A volte è necessario per determinate applicazioni: ad esempio è ansible creare contemporaneamente 2 windows separate. Niente di più.