qué que jfc ejemplos consiste componentes clase java multithreading swing

que - swing java definition



Java: Bibliotecas Swing y seguridad de subprocesos (11)

  1. Nunca haga tareas de ejecución prolongada en respuesta a un botón, evento, etc. ya que están en el hilo del evento. Si bloquea el hilo del evento, la GUI ENTERA no responderá por completo, lo que resultará en usuarios MUY cabreados. Es por eso que Swing parece lento y crujiente.

  2. Use Threads, Executors y SwingWorker para ejecutar tareas NO EN EL EDT (cadena de distribución de eventos).

  3. No actualice ni cree widgets fuera del EDT. Casi la única llamada que puede hacer fuera del EDT es Component.repaint (). Use SwingUtilitis.invokeLater para asegurarse de que se ejecute cierto código en el EDT.

  4. Use EDT Debug Techniques y una apariencia inteligente (como Substance , que verifica la violación de EDT)

Si sigues estas reglas, Swing puede hacer algunas GUIs muy atractivas y RESPUESTAS

Un ejemplo de algunos REALMENTE increíble trabajo de UI Swing: Palantir Technologies . Nota: NO trabajo para ellos, solo un ejemplo de increíble swing. No se avergüence de ninguna demostración pública ... Su blog es bueno, escaso, pero bueno

A menudo escuché críticas sobre la falta de seguridad de las hebras en las bibliotecas de Swing. Sin embargo, no estoy seguro de lo que estaría haciendo en mi propio código con podría causar problemas:

¿En qué situaciones entra en juego el hecho de que Swing no es seguro para subprocesos?

¿Qué debería evitar activamente?


Aquí hay un patrón para hacer swing swing-freindly.

Acción de la subclase (MiAcción) y hacer que su acción sea enhebrada. Haga que el constructor tome un NOMBRE de cadena.

Dale un método abstracto actionImpl ().

Deja que se vea como ... (advertencia de pseudocódigo)

doAction(){ new Thread(){ public void run(){ //kick off thread to do actionImpl(). actionImpl(); MyAction.this.interrupt(); }.start(); // use a worker pool if you care about garbage. try { sleep(300); Go to a busy cursor sleep(600); Show a busy dialog(Name) // name comes in handy here } catch( interrupted exception){ show normal cursor }

Puede registrar el tiempo necesario para la tarea, y la próxima vez, su diálogo puede mostrar una estimación decente.

Si quieres ser realmente agradable, duerme en otro hilo de trabajo también.


Esta es una de esas preguntas que me alegra que haya comprado el libro de Robinson & Vorobiev en Swing .

Todo lo que acceda al estado de un java.awt.Component debe ejecutar dentro del EDT, con tres excepciones: cualquier documento específicamente documentado como seguro para subprocesos, como repaint() , revalidate() e invalidate() ; cualquier componente en una interfaz de usuario que aún no se haya realizado ; y cualquier Componente en un Applet antes de que se haya llamado al start() de Applet start() .

Los métodos especialmente fabricados a prueba de hilos son tan poco comunes que a menudo es suficiente simplemente recordar los que sí lo son; generalmente también puede salirse con la suya asumiendo que no existen tales métodos (es perfectamente seguro envolver una llamada de repintado en un SwingWorker, por ejemplo).

Realizado significa que el Componente es un contenedor de nivel superior (como JFrame) en el que se ha llamado a cualquiera de setVisible(true) , show() o pack() o se ha agregado a un Componente realizado. Esto significa que está perfectamente bien construir su UI en el método main (), como lo hacen muchos ejemplos de tutoriales, ya que no llaman a setVisible(true) en el contenedor de nivel superior hasta que cada Componente se haya agregado a él, fuentes y bordes configurado, etc.

Por razones similares, es perfectamente seguro construir su UI de applet en su método init() , y luego llamar a start() vez que esté todo construido.

Envolver los siguientes cambios de componentes en Runnables para enviarlos a invokeLater() es fácil de obtener inmediatamente después de hacerlo solo unas pocas veces. Lo único que me molesta es leer el estado de un Componente (por ejemplo, someTextField.getText() ) de otro hilo. Técnicamente, esto también debe estar envuelto en invokeLater() ; en la práctica, puede hacer que el código sea feo y rápido, y con frecuencia no me molesto, o tengo cuidado de obtener esa información en el momento inicial del manejo del evento (normalmente es el momento adecuado para hacerlo en la mayoría de los casos).


Evite activamente realizar cualquier trabajo de Swing excepto en el hilo de envío del evento. Swing fue escrito para ser fácil de extender y Sun decidió que un modelo de un solo hilo era mejor para esto.

No he tenido problemas mientras sigo mi consejo anterior. Hay algunas circunstancias en las que puede ''cambiar'' de otros hilos pero nunca he encontrado la necesidad.


La frase ''hilo-inseguro'' suena como si hubiera algo inherentemente malo (ya sabes ... ''seguro'' - bueno, ''inseguro'' - malo). La realidad es que la seguridad de los hilos tiene un costo: los objetos ensartables a menudo son mucho más complejos de implementar (y Swing es lo suficientemente complejo incluso como lo es).

Además, la seguridad de la hebra se logra utilizando estrategias de bloqueo (lento) o de comparación y cambio (complejo). Dado que la GUI interactúa con humanos, que tienden a ser impredecibles y difíciles de sincronizar, muchos kits de herramientas han decidido canalizar todos los eventos a través de una única bomba de evento. Esto es cierto para Windows, Swing, SWT, GTK y probablemente otros. En realidad, no conozco un solo juego de herramientas GUI que sea realmente seguro para subprocesos (lo que significa que puede manipular el estado interno de sus objetos desde cualquier hilo).

Lo que generalmente se hace en cambio es que las GUI proporcionan una manera de lidiar con la inseguridad del hilo. Como señalaron otros, Swing siempre ha proporcionado SwingUtilities.invokeLater () algo simplista. Java 6 incluye el excelente SwingWorker (disponible para versiones anteriores de Swinglabs.org). También hay bibliotecas de terceros como Foxtrot para administrar los hilos en el contexto Swing.

La notoriedad de Swing se debe a que los diseñadores han adoptado el enfoque liviano de asumir que el desarrollador hará lo correcto y no parará el EDT ni modificará los componentes desde fuera del EDT. Han declarado su política de enhebrado alto y claro y depende de los desarrolladores seguirla.

Es trivial hacer que cada API oscilante publique un trabajo en el EDT para cada conjunto de propiedades, invalidación, etc., lo que lo haría inseguro, pero a costa de desaceleraciones masivas. Incluso puedes hacerlo tú mismo usando AOP. A modo de comparación, SWT arroja excepciones cuando se accede a un componente desde un hilo equivocado.


No es solo que Swing no es seguro para subprocesos (no mucho), pero es hostil al hilo. Si comienza a hacer cosas de Swing en un solo hilo (que no sea el EDT), entonces cuando en los casos en que Swing cambie al EDT (no documentado) puede haber problemas de seguridad de hilos. Incluso el texto Swing, que apunta a ser seguro para subprocesos, no es útil para subprocesos (por ejemplo, para anexar a un documento primero debe encontrar la longitud, que puede cambiar antes de la inserción).

Entonces, haz todas las manipulaciones de Swing en el EDT. Tenga en cuenta que el EDT no es el hilo al que se llama el principal, así que empiece sus aplicaciones Swing (simples) como esta repetitiva:

class MyApp { public static void main(String[] args) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { runEDT(); }}); } private static void runEDT() { assert java.awt.EventQueue.isDispatchThread(); ...



Si está utilizando Java 6, entonces SwingWorker es sin duda la forma más fácil de lidiar con esto.

Básicamente, quiere asegurarse de que todo lo que cambie una IU se realice en EventDispatchThread.

Esto se puede encontrar utilizando el método SwingUtilities.isEventDispatchThread () para indicarle si se encuentra en él (generalmente no es una buena idea, debe saber qué hilo está activo).

Si no está en el EDT, entonces usa SwingUtilities.invokeLater () y SwingUtilities.invokeAndWait () para invocar un Runnable en el EDT.

Si actualiza UI que no está en el EDT, obtiene un comportamiento increíblemente extraño. Personalmente, no considero que esto sea una falla de Swing, obtienes una buena eficacia al no tener que sincronizar todos los hilos para proporcionar una actualización de UI, solo necesitas recordar esa advertencia.


Tenga en cuenta que ni siquiera las interfaces del modelo son seguras para hilos. El tamaño y el contenido se consultan con métodos de obtención separados, por lo que no hay forma de sincronizarlos.

La actualización del estado del modelo desde otro subproceso permite, al menos, pintar una situación en la que el tamaño es aún mayor (la fila de la tabla aún está en su lugar), pero el contenido ya no está allí.

Actualizar el estado del modelo siempre en EDT evita esto.


Una alternativa al uso de máscaras inteligentes como la sustancia es crear el siguiente método de utilidad:

public final static void checkOnEventDispatchThread() { if (!SwingUtilities.isEventDispatchThread()) { throw new RuntimeException("This method can only be run on the EDT"); } }

Llámalo en cada método que escribas que se requiere para estar en el hilo de envío del evento. Una ventaja de esto sería deshabilitar y habilitar comprobaciones de todo el sistema muy rápidamente, por ejemplo, posiblemente eliminar esto en producción.

Tenga en cuenta que las máscaras inteligentes pueden, por supuesto, proporcionar cobertura adicional y solo esto.


invokeLater () y invokeAndWait () realmente DEBEN ser utilizados cuando se realiza cualquier interacción con componentes GUI de cualquier hilo que NO sea el EDT.

Puede funcionar durante el desarrollo, pero al igual que la mayoría de los errores simultáneos, comenzará a aparecer excepciones extrañas que parecen no estar relacionadas y que ocurren de manera no determinante, generalmente detectadas DESPUÉS de que los haya enviado un usuario real. No está bien.

Además, no tiene confianza en que su aplicación continuará funcionando en futuras CPU con más y más núcleos, que son más propensos a encontrar problemas de subprocesos debido a que son verdaderamente concurrentes en lugar de simplemente simulados por el sistema operativo.

Sí, se pone feo envolviendo todas las llamadas de método en el EDT en una instancia de Runnable, pero eso es Java para ti. Hasta que tengamos cierres, solo tienes que vivir con eso.