2010-03-20 10 views
6

Sé lo que significa "hilo" y si entiendo el hilo de envío de eventos (EDT) como "solo un hilo", explica mucho pero, aparentemente, no explica todo.¿Cuál es el hilo de envío de eventos?

No entiendo qué tiene de especial este hilo. Por ejemplo, no entiendo por qué deberíamos comenzar una GUI en un EDT? ¿Por qué el hilo "principal" es la base para GUI? Bueno, si simplemente no queremos ocupar el hilo principal, ¿por qué no podemos iniciar la GUI solo en "otro hilo" por qué debería ser un hilo "especial" llamado EDT?

Entonces, ¿no entiendo por qué no podemos iniciar el EDT como cualquier otro hilo? Por qué deberíamos usar alguna herramienta especial (llamada invokeLater). Y por qué GUI, a diferencia de cualquier otro hilo, no se inicia de inmediato. Deberíamos esperar hasta que esté listo para aceptar nuestro trabajo. ¿Es porque EDT puede, potencialmente, ejecutar varias tareas simultáneamente?

Si decide responder esta pregunta, podría utilizar una terminología muy simple porque de lo contrario, me temo que no seré capaz de entender la respuesta.

añadido:

Siempre pensé que tenemos una "tarea" por hilo. Entonces, en cada hilo, ejecutamos una secuencia predefinida de comandos. Pero me parece que en el caso de que se envíe el hilo, podemos tener una tarea de corte. Bueno, no se ejecutan simultáneamente (el hilo cambia entre diferentes tareas pero todavía hay varias tareas en un hilo). ¿Es correcto? Por ejemplo, hay un hilo en el EDT que muestra la ventana principal, y luego adicionalmente enviamos al EDT otra tarea que debería actualizar uno de los componentes de la ventana y EDT ejecutará esta nueva tarea siempre que esté lista. ¿EDT difiere de otros hilos de esta manera?

+0

EDT es el mismo hilo que cualquier otro. Hay una tarea para cada hilo, en Java se expresa como un 'Runnable' pasado al' T hread' o un método 'run()'. Sin embargo, imagine tal tarea para un hilo: esperar en una cola y ejecutar cada tarea ('Runnable') que se agrega a mi cola. Así es como funciona. – pajton

Respuesta

6

El hilo de envío de eventos es el hilo que maneja todos los eventos de GUI y administra su GUI de Swing. Se inicia en algún lugar del código Swing si tiene alguna GUI en su programa. La razón por la que se hace entre bastidores es por la simplicidad: no tiene que preocuparse por iniciar y administrar un hilo adicional usted mismo.

En cuanto al hecho de que debe actualizar su GUI con invokeLater() es debido a problemas de simultaneidad. La GUI solo se puede modificar a partir de un hilo porque Swing no es seguro para subprocesos (vale la pena señalar que más de toolkits no son seguros para subprocesos, hay un nice article que da algunas ideas de por qué). Es por eso que debe enviar todas las actualizaciones de GUI para ejecutar en EDT.

Puede leer más sobre la concurrencia en Swing y la cadena de envío de eventos en Sun tutorial on concurrency in Swing. Además, si desea ver cómo se podría hacer esto de otra manera, es posible que desee consultar SWT toolkit. En SWT tienes que administrar EDT por ti mismo.

3
What is the EDT? 

Es una solución hacky torno a la gran cantidad de problemas de concurrencia que el API Swing tiene;)

En serio, una gran cantidad de componentes Swing no son "hilo de seguridad" (algunos programadores famosos fueron tan lejos como llamar Swing "hilo hostil"). Al tener un hilo único donde se realizan todas las actualizaciones a estos componentes hostiles, se está eludiendo una gran cantidad de posibles problemas de concurrencia. Además de eso, también se le garantiza que ejecutará Runnable que pase a través de invokeLater en un orden secuencial.

Tenga en cuenta que no se trata sólo de que está esquivando el problema de concurrencia: que debe respetar directrices de Sun con respecto a lo que debe y lo que no se debe hacer en el EDT o tendrá graves problemas en su aplicación.

Otra ventaja es que algunos componentes de Swing tienden a arrojar excepciones no deseadas y cuando esto sucede se solucionan automágicamente y no bloquean el EDT (AFAIK si realmente logras matar al EDT se reinicia automáticamente).

En otras palabras: no tiene que ocuparse de todos los componentes Swing rotos y las excepciones que se arrojan: el EDT se está ocupando de eso (solo eche un vistazo a los innumerables errores Swing arrojando excepciones en el error de Sun desfile, es fascinante ... Y sin embargo, la mayoría de las aplicaciones siguen funcionando normalmente).

Además, al hacer solo lo que es obligatorio en el EDT permite que la GUI de su aplicación se mantenga "receptiva" incluso si es difícil que haya tareas ejecutándose en segundo plano.

3

Lo importante es recordar que las clases Swing no son seguras para subprocesos.Esto significa que siempre debe llamar a los métodos Swing del mismo hilo, o corre el riesgo de obtener un comportamiento extraño o indefinido.

Así que la solución: solo llame a los métodos de Swing desde un único hilo. Este es el hilo EDT - no es especial en ninguna otra forma que no sea que es el hilo designado para llamar a los métodos de swing.

Ahora puede preguntarse por qué los métodos Swing no son seguros para subprocesos? Después de varios intentos infructuosos, los diseñadores de los juegos de herramientas de GUI descubrieron que es inherentemente imposible diseñar un juego de herramientas GUI seguro para subprocesos. Con demasiada frecuencia los eventos se pasan en direcciones opuestas (eventos de entrada de abajo hacia arriba, eventos de aplicación de arriba a abajo) que siempre conducen a interbloqueos. Entonces esa es la forma en que es.

+0

@amarillion: es un poco especial porque las excepciones que suceden en el EDT se comportan de manera diferente a las excepciones lanzadas en otros hilos y que si matas el EDT, se reiniciará automáticamente. – SyntaxT3rr0r

+0

OK. Esto me suena como una solución práctica. Entonces, puse mi aplicación GUI en el EDT (usando 'invokeLater') y luego, si tengo muchos otros hilos, y quiero llamar a la aplicación GUI desde este hilo, solo hago estas llamadas usando' invokeLater' y todo debe estar bien. Funciona de esta manera? – Roman

+0

@Roman: exactamente. Pero para una aplicación simple, donde usted hace todo el trabajo en ActionListeners y otros manejadores de eventos, main() puede ser el único método que no está en el EDT. Entonces llamas a invokeLater solo una vez. Por supuesto, esto solo es cierto para aplicaciones sencillas, pero es suficiente saber para empezar con java. – amarillion

6

Siempre pensé que teníamos una "tarea" por hilo. Entonces, en cada hilo , ejecutamos una secuencia predefinida de comandos . Pero me parece que en el hilo de envío de eventos podemos tener la tarea de cortar. Bueno, no son ejecutados simultáneamente (thread cambia entre tareas diferentes pero todavía hay varias tareas en un hilo ). ¿Es correcto? Por ejemplo hay un hilo en el EDT, que mostrar la ventana principal, y luego , además, a que enviamos a la EDT otra tarea que debe actualizar uno de los componentes de la ventana y EDT ejecutará esta nueva tarea cada vez que está listo. ¿EDT difiere de otros hilos de esta manera?

No, el EDT no es fundamentalmente diferente de otros hilos. Y "tarea" no es una buena palabra para usar, ya que podría confundirse con procesos de nivel de sistema operativo (que a menudo también se denominan tareas). Mejor uso Runnable, la interfaz utilizada para dar código al EDT para ejecutar a través de invokeLater().

El EDT está básicamente conectado a una cola de cosas que tiene que hacer. Cuando el usuario hace clic en un botón de la GUI, entra en la cola un Runnable que notifica a todos los oyentes conectados al botón. Cuando se cambia el tamaño de una ventana, una Runnable haciendo revalidar la repintación & entra en la cola. Y cuando usa invokeLater(), su Runnable entra en la cola.

La EDT simplemente ejecuta un bucle sin fin que dice "tomar un Runnable de la cola (y si es el sueño vacía hasta que reciba un aviso de que no lo es) y ejecutarlo.

Por lo tanto, ejecuta todos esos pequeños Runnable trozos de código uno tras otro, de modo que cada uno de ellos tenga básicamente la GUI por sí solo mientras se ejecuta, y no tiene que preocuparse por sincronizar nada. Cuando manipula la GUI desde otro subproceso, esta suposición se interrumpe y puede terminar con la GUI en estado corrupto

Cuestiones relacionadas