Explicación del hilo de distribución de eventos de Java
Recientemente comencé a aprender y explorar los conceptos básicos de la programación GUI en Java.
Después de haber estado programando por un tiempo, solo he hecho trabajo de backend o trabajo y, como resultado, lo más cerca que he estado de las interfaces de usuario es la consola de comandos (vergonzoso, lo sé).
Estoy usando Swing y, hasta donde puedo entender, eso significa que, por extensión, también estoy usando AWT.
Mi pregunta se basa en este fragmento de código:
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new frame.setVisible(true);
}
} );
He estado investigando esto por un tiempo porque quería comprender completamente este extraño fragmento de código y me encontré con el término "Subproceso de envío de eventos" varias veces. Corríjanme si me equivoco pero según tengo entendido; tiene que ver con el uso de múltiples subprocesos y cómo Java Swing interpreta esos subprocesos. También deduzco que el código anterior se utiliza para garantizar que todos los subprocesos sean "seguros" antes de crear la ventana, de ahí el invokeLater?
He leído que:
"Solo puedes llamar a métodos que operan en el marco desde el hilo de distribución de eventos"
y que sólo bajo ciertas circunstancias se pueden llamar métodos que operan en el marco desde el método principal.
¿Alguien puede aclararme qué es exactamente el hilo de envío de eventos?
¿Cómo se relaciona con múltiples subprocesos de ejecución y cómo no es seguro llamar a esos subprocesos desde el método principal? Además, ¿por qué necesitamos esta invocación más tarde?
¿No podemos simplemente crear la ventana como cualquier otro objeto?
Me he topado con un obstáculo en mi investigación porque no entiendo estas relaciones e ideas.
Una nota al margen es que me gusta basar mis conocimientos en una comprensión profunda, ya que creo que esto conduce al mejor resultado general y, como resultado, a los mejores programas. Si entiendo en profundidad cómo funciona algo, entonces puedes usar los consejos y ajustes de manera efectiva en lugar de simplemente repetirlos como un loro en el código, así que no temas darme algunas explicaciones más detalladas y ampliar mis conocimientos.
Gracias.
El hilo de envío de eventos es un hilo especial administrado por AWT. Básicamente, es un hilo que se ejecuta en un bucle infinito, procesando eventos.
Los métodos java.awt.EventQueue.invokeLater
y javax.swing.SwingUtilities.invokeLater
son una forma de proporcionar código que se ejecutará en la cola de eventos. Escribir un marco de 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 la GUI se realicen en un único subproceso especial. Todos los controladores de eventos se ejecutarán en este hilo y todo el código que modifique la GUI también debería funcionar en este hilo.
Ahora, AWT generalmente no verifica que no esté emitiendo comandos GUI desde otro subproceso (el marco WPF para C# hace esto), lo que significa que es posible escribir una gran cantidad de código y ser bastante agnóstico ante esto y no tener ningún problema. Pero esto puede conducir a un comportamiento indefinido, por lo que lo mejor que se puede hacer es asegurarse siempre de que el código GUI se ejecute en el subproceso de envío de eventos. invokeLater
proporciona un mecanismo para hacer esto.
Un ejemplo clásico es que necesita ejecutar una operación de larga duración, como descargar un archivo. Entonces, inicia un hilo para realizar esta acción y luego, cuando se completa, lo utiliza invokeLater
para actualizar la interfaz de usuario. Si no la usó invokeLater
y en su lugar simplemente actualizó la interfaz de usuario directamente, es posible que tenga una condición de carrera y podría ocurrir un comportamiento indefinido.
Wikipedia tiene más información.
Además, si tiene curiosidad por saber por qué los autores de AWT no hacen que el kit de herramientas sea multiproceso, aquí tiene un buen artículo.
EventDispatchThread
(EDT) es un hilo especial reservado solo para Swing GUI y *eventos relacionados con Swing, por ejemplo, crear/cambiar/actualizar Swing JComponents , más para preguntas formuladas aquí y aquí
toda la salida a la GUI desde BackGround Tasks
, Runnable#Thread
debe incluirse en invokeLater() , desde los objetos sincronizados hastainvokeAndWait();