5

L'istruzione sopra riportata è menzionata nello SwingWorker javadoc.Perché è necessario accedere ai componenti di Swing solo sul thread di invio eventi?

In un'applicazione ho visto una lunga attività in background eseguita in un thread distinto e aggiorna anche l'interfaccia utente senza problemi (un riferimento a un componente Swing era accessibile).

Potrebbe succedere qualcosa di brutto?

+2

* "Potrebbe succedere qualcosa di brutto?" * - Sì. In poche parole, Swing non è thread-safe, non protegge da più thread l'accesso a proprietà diverse, il che significa che si entra in uno stato incoerente. Ricorda che non controlli il processo di verniciatura, quindi qualcosa potrebbe essere dipinto mentre lo stai cambiando ... questi problemi sono difficili da replicare e rintracciare e la cosa peggiore è che sembrano accadere solo sulle macchine degli utenti .. .. – MadProgrammer

+0

Non illuderti, questa è davvero, davvero pericolosa e davvero una pessima idea – MadProgrammer

+0

1. perché, 2. la mia curiosità è davvero un motivo per pubblicare una domanda su, 3. nota c'è un'enorme differenza nella sicurezza del thread tra Java6 e Java7/8, 4. voto per chiudere come troppo ampio (senza un SSCCE/MCVE, breve, eseguibile, compilabile, con valore hard per la GUI Swing nella variabile locale) – mKorbel

risposta

6

È perché il Java memory model non garantisce che le scritture di memoria di un thread saranno visibili ad altri thread a meno che non si utilizzi una qualche forma di sincronizzazione. Per prestazioni e semplicità, Swing non è sincronizzato. Pertanto, le scritture da altri thread potrebbero non essere mai visibili all'EDT.

L'applicazione che hai visto potrebbe funzionare la maggior parte del tempo, e potrebbe persino funzionare tutto il tempo in alcuni ambienti. Ma quando non funziona, fallirà in modi davvero strani che sono difficili da riprodurre.

+0

[Ecco] (https://weblogs.java.net/blog/kgh/archive/2004/10/multithreaded_t.html) un argomento sul perché Swing * ha * per essere singlethreaded. "Per semplicità" fa sembrare il pigro design o un difetto. – DSquare

+0

@DSquare Ottima lettura, e penso che si applica a più di un semplice toolkit dell'interfaccia utente. Molti programmi multi-thread potrebbero essere notevolmente semplificati da un approccio con coda di eventi a thread singolo. E quando si parla di software, direi che la "semplicità" ha una connotazione fortemente positiva. :) –

5

Tutti i componenti di Swing sono implementati per l'accesso da un singolo thread (il thread di dispacciamento dell'evento). Quindi non ci sono protezioni contro accessi concorrenti e modifiche simultanee di variabili e campi.

Se siete fortunati, tutto funziona bene. Ma non puoi fare affidamento su di esso e lo stesso codice può avere enormi problemi alla prossima esecuzione.

Un semplice esempio:

La procedura di vernice di un JLabel contiene il codice seguente (semplificato) (tratto da BasicLabelUI classe):

# assume your label is enabled 
    Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon(); 

    # what happens if another thread calls label.setEnabled(false) at this point? 

    if (icon != null) { 
     icon.paintIcon(c, g, paintIconR.x, paintIconR.y); 
    } 

    if (label.isEnabled()) { 
     paintEnabledText(label, g, clippedText, textX, textY); 
    } 
    else { 
     paintDisabledText(label, g, clippedText, textX, textY); 
    } 

Per esempio se si chiama setEnabled() da altri thread rispetto all'EDT, sarebbe possibile ottenere un'etichetta con l'icona abilitata, ma il testo dipinto disabilitato.

Problemi correlati