2011-08-27 29 views
48

Recientemente comencé a aprender y explorar los principios básicos de la programación de GUI en Java.Explicación del hilo de envío de eventos Java

Habiendo sido programación durante un tiempo sólo he hecho el trabajo de back-end o en el trabajo y como resultado lo más cerca que he estado de interfaces de usuario es la consola de comandos (embarazosa lo sé).

estoy usando Swing y por lo que he entendido que significa por extensión También estoy usando AWT.

Mi pregunta se basa en este pedazo de código:

java.awt.EventQueue.invokeLater(new Runnable() { 
    public void run() { 
     new frame.setVisible(true); 
    } 
}); 

he estado investigando esto durante un tiempo, ya que quería entender completamente esta extraña pieza de código y he encontrado el término 'de despacho de eventos Enhebrar 'varias veces. Corrígeme si me equivoco, pero tal como lo entiendo; tiene que ver con el uso de varios hilos y cómo Java Swing interpreta esos hilos. Supongo que el código anterior se usa para asegurarse de que todos los hilos estén "seguros" antes de que cree la ventana, de ahí el invokeLater?

He leído que:

"Sólo se puede llamar a los métodos que operan en el marco de la rosca de Despacho de Eventos"

y que sólo bajo ciertas circunstancias se puede llamar a los métodos que se operar en el marco del método principal.

Puede alguien me aclare qué es exactamente el hilo de Despacho de Eventos es?

¿Cómo se relaciona con múltiples hilos de ejecución y cómo esos hilos no son seguros para llamar desde el método principal? Además, ¿por qué necesitamos este invokeLater?

¿No podemos simplemente crear la ventana como cualquier otro objeto?

He golpeado un poco de un obstáculo en el camino en mi investigación, ya que no estoy agarrando estas relaciones e ideas.

Una nota al margen es que me gusta basar mis conocimientos sobre la comprensión en profundidad ya que creo que esto conduce al mejor resultado global y como resultado los mejores programas. Si entiendo en profundidad cómo funciona algo, entonces puede utilizar los consejos y ajustes de manera efectiva en lugar de simplemente repetirlos en el código, así que no dude en darme explicaciones adicionales y ampliar mis conocimientos.

Gracias.

Respuesta

54

El subproceso EventDispatching es un subproceso especial administrado por el AWT. Básicamente es un hilo que se ejecuta en un evento de procesamiento de bucle infinito. El método java.awt.EventQueue.invokeLater es una forma especial de proporcionar algún código que se ejecutará en la cola de eventos. Escribir un interfaz de usuario que sea seguro en un entorno de subprocesos múltiples es muy difícil, por lo que los autores de AWT decidieron que solo permitirían que las operaciones en objetos de GUI tuvieran lugar en un único hilo especial. Todos los controladores de eventos se ejecutarán en este hilo y todos los códigos que modifiquen la interfaz gráfica de usuario también deberían operar en este hilo.

Ahora el AWT no suele comprobar que no está emitiendo comandos GUI desde otro hilo (El marco WPF para C# hace hacer esto).por lo que es posible escribir un montón de código y ser bastante agnóstico y no tener problemas. Pero esto puede llevar a un comportamiento indefinido, por lo que lo mejor es asegurarse siempre de que el código GUI se ejecute en el hilo del despachador de eventos. invokeLater proporciona un mecanismo para hacer esto.

Por lo tanto, un ejemplo clásico es que necesita ejecutar una operación de larga ejecución, como descargar un archivo. Entonces, inicia un hilo para realizar esta acción y luego, cuando se complete, utilizará invokeLater para actualizar la interfaz de usuario. Si no usó invokeLater y en su lugar acaba de actualizar la interfaz de usuario directamente, es posible que tenga una condición de carrera y un comportamiento indefinido podría ocurrir.

Wikipedia tiene más información: http://en.wikipedia.org/wiki/Event_dispatching_thread

Además, si usted es curioso por qué los autores AWT no se limite a hacer que la Guía multihilo aquí es un buen artículo: https://community.oracle.com/blogs/kgh/2004/10/19/multithreaded-toolkits-failed-dream

+0

Mis disculpas por la última respuesta, I' he estado al tanto del trabajo. Tu publicación realmente ha respondido de manera bastante concisa a muchas de mis preguntas, por lo que me gustaría agradecerte por ello. Bien, entonces si entiendo correctamente, entonces, para operar en la GUI, debo usar el método invokeLater() con un objeto ejecutable y al hacerlo puedo asegurarme de estar siempre utilizando el EDT. También leí sobre la clase SwingWorker que ahora es oficialmente compatible. ¿Se consideraría que esta clase es superior al método invokeLater o estoy malentendiendo y resuelven dos problemas diferentes? – linuscash

+1

Hay una serie de casos en los que se garantiza que ya se están ejecutando en el EDT, por ejemplo, controladores de eventos (ActionListeners, ClickListeners), por lo que no es necesario utilizar invokeLater desde allí. Creo que un SwingWorker es solo un hilo que tiene un mecanismo especial para interactuar con el EDT (probablemente a través de invokeLater). Así que definitivamente usaría eso si fuera apropiado. – luke

+0

De acuerdo, eso tiene sentido, muchas gracias. Has aclarado bastantes discrepancias para mí. – linuscash

11

EventDispatchThread (EDT) está reservado hilo especial solo para los eventos relacionados con Swing GUI y * Swing, por ejemplo crear/cambiar/actualizar Swing JComponents, más para preguntas here y here

toda la salida a la interfaz gráfica de usuario de BackGround Tasks, Runnable#Thread debe ser envuelto en invokeLater(), desde sincronizan los objetos en invokeAndWait();

Cuestiones relacionadas