2011-02-05 3 views
15
java.awt.EventQueue.invokeLater(new Runnable() { 
    public void run() { 
     new NewJFrame().setVisible(true); 
    } 
}); 

Per favore dimmi cosa fa il codice sopra in realtà. Sto cercando spiegazioni linea per linea. soprattutto la prima linea e dimmi perché la usiamo e in quali scenari dobbiamo usarla.Spiegare cosa fa il seguente codice?

risposta

27

In questo esempio viene visualizzata una classe qualsiasi che deriva da Runnable. Questa classe anonima sovrascrive il metodo di esecuzione dell'interfaccia eseguibile. Quindi questa classe anonima viene istanziata e passata al metodo EventQueue.invokeLater, che è un metodo statico. Questo metodo aggiunge l'oggetto in ... beh ... l'eventQueue. In EvenQueue ci sono molti eventi, come eventi di tastiera o eventi del mouse o altro. Esiste una discussione che esegue continuamente il polling dei dati da questa coda. Una volta che quel thread raggiunge la classe anonima che è stata istanziata qui, eseguirà il metodo run(), che istanzia un oggetto di classe NewJFrame e lo imposta per essere visibile.

L'intero scopo di questo è complicato è che la nuova parte JFrame(). SetVisible (true) non viene eseguita nel thread principale, ma nel thread di invio dell'evento. In Swing è necessario eseguire tutto il codice che modifica l'interfaccia utente nel thread di invio eventi.

+0

hai fatto un buon lavoro e io sono chiaro con questi concetti ora !! grazie .. – Deepak

+0

E cosa succederebbe se lo mettessi nel metodo principale, senza alcun involucro? 'public static void main (String args []) {New JFrame(). SetVisible (true);}' – Martin

+1

@Martin: Quindi si infrange la regola che il codice che interessa l'interfaccia utente deve essere eseguito nel thread di invio dell'evento. Questo potrebbe accadere per funzionare (la maggior parte delle volte), ma potrebbe anche causare una serie di errori relativi alle condizioni di gara, ecc. È difficile prevedere cosa potrebbe accadere. Forse incappi in errori di disegno, forse no. – yankee

2

Questo è un blocco di codice che viene richiesto di eseguire in un secondo momento (a volte chiamato deferred). La classe interna (new Runnable() {...}) ti consente essenzialmente di passare un blocco di codice che verrà eseguito. Il invokeLater method garantisce che il blocco di codice verrà eseguito, ma non fornisce garanzie su quando. A volte non è sicuro avere un determinato codice eseguito immediatamente, ed è troppo prolisso per eseguire autonomamente il multi-threading. Quindi Java fornisce questo metodo di utilità per eseguire il codice in modo sicuro. Il codice verrà eseguito molto presto, ma non prima che sia sicuro farlo.

+1

hai un buon contenuto e ho capito bene invokeLater parte .. – Deepak

1

La chiamata invokeLater inserirà il runnable specificato su una coda da elaborare successivamente. Cioè, il codice all'interno del metodo run() non è stato ancora eseguito quando ritorna la chiamata al metodo invokeLater.

Esistono due casi d'uso tipici per questo tipo di codice.

  1. Il codice attualmente in esecuzione viene eseguito in un thread in background. I thread in background non possono accedere alla maggior parte dell'API swing. Maggiori informazioni here per la ragione di questo. Se il thread corrente è già il thread dell'interfaccia utente, non c'è alcun motivo e la chiamata può essere rimossa in tutta sicurezza.
  2. Il blocco corrente deve essere chiuso, ovvero il codice raggiunge l'ultima parentesi. Ciò potrebbe causare il rilascio di risorse e così via. Questo non è così comune.

Una classe anonima viene passata come parametro alla chiamata invokeLater. È lo stesso di questo codice.

private void foo() 
{ 
    java.awt.EventQueue.invokeLater(new JFrameCreator()); 
} 
private class JFrameCreator implements Runnable 
{ 
    public void run() { 
    new NewJFrame().setVisible(true); 
    } 
} 
+0

questa è una buona spiegazione .. solo tel me perché usiamo runnable() qui ?? – Deepak

+0

e credo che (nuovo JFrameCreator()) creerà una classe anonima. Significa che quando questo thread viene elaborato, run() viene eseguito automaticamente. Mi dispiace se ti sto chiedendo qualcosa di completamente sbagliato. Voglio solo sapere run() e (nuovo JFrameCreator()) .. – Deepak

+0

No, scusa, ma questo non funzionerà. La classe JFrameCreator DEVE implementare Runnable (basta scrivere la classe JFrameCreator implementa Runnable). E @Deepak: No, non ci sono classi anonime coinvolte in questo esempio. – yankee

1

Source

Il metodo invokeLater() prende un oggetto Runnable come parametro. Invia quell'oggetto al thread di invio eventi, che esegue il metodo run(). Questo è il motivo per cui è sempre sicuro che il metodo run() esegua il codice Swing.

-IvarD

4

single-thread-modello e EDT

La maggior parte delle moderne librerie UI adottano la single-thread-model.Ciò significa che tutta la manipolazione delle componenti dell'interfaccia utente DEVE essere eseguita sullo stesso thread singolo. Perché? Questo perché consentire l'aggiornamento dei componenti dell'interfaccia utente da più thread porterà al caos dal most Swing object methods are not "thread safe". Per semplicità, efficienza e robustezza, viene adottato il modello a thread singolo.

In Swing, il thread che serve lo single-thread-model è chiamato Event Dispatching Thread, cioè EDT. Non è fornito da Swing. È fornito da Abstract Window Toolkit, ad esempio AWT.

Thread di lavoro vs UI filo

Un'applicazione GUI non banale di solito ha molti fili. Nella moderna applicazione GUI, ci possono essere molti thread di lavoro per fare lavori sporchi, ma c'è solo un thread di interfaccia utente (Swing chiama EDT) per aggiornare la GUI. I thread di lavoro di solito devono riflettere i loro progressi di lavoro nella GUI, quindi hanno bisogno di comunicare con il thread dell'interfaccia in merito. Quindi, come avviene questa comunicazione?

java.awt.EventQueue

La comunicazione avviene attraverso un modello di coda di messaggi. Lo java.awt.EventQueue è la classe che fornisce una coda eventi a livello globale. Questa coda eventi globale funge da canale di comunicazione per EDT. EDT preleva i messaggi da questo EventQueue e aggiorna i componenti UI di conseguenza. Se qualche altra parte del programma desidera modificare l'interfaccia utente, quella parte di codice deve chiamare EventQueue.invokeLater() o EventQueue.invokeAndWait() per accodare un messaggio in EventQueue. EDT elaborerà tutti i messaggi in sospeso in EventQueue e alla fine arriverà al messaggio.

il thread principale

tuo frammento di codice di solito risiede nel thread main(), il filo main può essere visto come una specie di worker thread qui. Solo che invece di aggiornare la GUI inviando messaggi a EventQueue, avvia la GUI. Ad ogni modo, l'iniziazione può essere vista come una specie di lavoro, anche.

Dopo l'avvio della GUI, il thread principale verrà chiuso e l'EDT impedirà l'uscita del processo.

E un'altra buona spiegazione:

Java Event-Dispatching Thread explanation

Un interessante articolo: Multi-threaded toolkit, a failed dream?

+0

Sembra che il tuo ultimo link sia marcito o sia stato posizionato male? Hai il link per quell'articolo? Sembra interessante. – code11

+0

@ code11 Grazie per averlo indicato. Link aggiornato. – smwikipedia