ejemplo java multithreading swing swingworker

java - ejemplo - ¿Cuál es la razón de ser de SwingWorker?



java swingworker ejemplo (7)

Por lo que puedo leer, se utiliza para enviar un nuevo hilo en una aplicación de swing para realizar un trabajo de "fondo", pero ¿cuál es el beneficio de usar este hilo en lugar de un hilo "normal"?

¿No es lo mismo usar un nuevo subproceso y cuando termine invoque un método de GUI usando SwingUtilities.invokeLater? ...

¿Que me estoy perdiendo aqui?

http://en.wikipedia.org/wiki/SwingWorker

http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html


SwingWorker es una implementación de un patrón común (en .Net lo leí, hay GuiWorker BackgroundWorker para esto), donde tiene que trabajar en un programa GUI, pero mantener la GUI en buen estado. El problema es que a menudo las bibliotecas de GUI no son seguras para múltiples hilos, por lo que la forma más común de implementar dichos trabajadores es usar el bucle de mensajes de la biblioteca para transferir mensajes al bucle de eventos de la aplicación.

Estas clases te permiten actualizar fácilmente tu GUI. Usualmente, tienen un método de update(int status) que es llamado por el hilo, despachado por la clase y manejado por la GUI, mientras el hilo continúa su trabajo.

Usando hilos normales, necesitaría codificar sus propios eventos o algún otro mecanismo de mensajería para esta tarea, lo que puede ser complicado si necesita esta funcionalidad a menudo. Usando invokeLater en Java, por ejemplo, mezcle el código para actualizar la GUI en el código para hacer el trabajo. SwingWorker te permite mantener las cosas separadas.


para responder a tu pregunta, no te estás perdiendo nada. esta clase es solo una utilidad conveniente para completar la funcionalidad que usted describió (inicie otra cadena para hacer el trabajo de fondo y luego invoque una acción final en la EDT con los resultados).


Un ejemplo de código:

import org.jdesktop.swingx.util.SwingWorker; // This one is from swingx // another one is built in // since JDK 1.6 AFAIK? public class SwingWorkerTest { public static void main( String[] args ) { /** * First method */ new Thread() { public void run() { /** Do work that would freeze GUI here */ final Object result = new Object(); java.awt.EventQueue.invokeLater( new Runnable() { public void run() { /** Update GUI here */ } } ); } }.start(); /** * Second method */ new SwingWorker< Object , Object >() { protected Object doInBackground() throws Exception { /** Do work that would freeze GUI here */ return null; } protected void done() { try { Object result = get(); /** Update GUI here */ } catch ( Exception ex ) { ex.printStackTrace(); if ( ex instanceof java.lang.InterruptedException ) return; } } }.execute(); } }

La elección siempre depende de las preferencias personales y el caso de uso.

El segundo método tiene una ventaja cuando se refactoriza. Puede convertir más fácilmente la clase anónima a una clase interna cuando el método en el que se utiliza es demasiado grande.

Mi preferencia personal va al segundo, ya que hemos creado un marco en el que se pueden agregar SwingWorkers y se ejecutan uno tras otro ...


SwingWorker hace que el código de ejemplo trivial sea mucho más conciso. Sin embargo, crea una bola de barro. Las comunicaciones hacia y desde la GUI y la lógica ejecutada están todas juntas. Por lo tanto, no me gustaría ver que se use en el código de producción real.


SwingWorker es mucho más fácil que eliminar con tus propios subprocesos porque te da dos cosas que son dolorosas de forma manual, coordina el subproceso entre la UI y el proceso en segundo plano y realiza bucles que funcionan de manera efectiva y que continúan funcionando y enviando actualizaciones a la interfaz de usuario de forma incremental. como procesar una gran cantidad de datos, o cargar una lista grande. La desventaja (o ventaja) depende de cómo se mire, es que oculta la implementación subyacente, por lo que la versión futura puede tener un comportamiento, rendimiento, etc. diferente, lo que puede ser indeseable. Lo encontré bastante útil como pegamento entre un evento de interfaz de usuario y mi propio código de comando, SwingWorker mantiene el enlace a la interfaz de usuario y mi código almacena datos.


Cuando se trabaja con Swing, es importante saber que el procesamiento de oscilación principal (es decir, el renderizado) ocurre en un único hilo (que no es el hilo principal). Esto a menudo se denomina subproceso de evento Swing o awt. Quienes estén familiarizados con el JDK pre 1.6 recordarán el error del "rectángulo gris" si pasaron demasiado tiempo en un despachador de eventos para un componente de columpio. Qué significa esto. En cualquier aplicación swing tendrás 2 hilos en ejecución con los que tendrás que lidiar ahora. Normalmente, si todas sus operaciones dentro de un despachador de eventos (el código que se activa dice cuando se hace clic en un botón) es corto (es decir, cambiando el estado de un botón siwng), puede ejecutar esto dentro del despachador de eventos. Si su aplicación llamará a un servicio web o a una base de datos, o si su estado de aplicación está impulsado por eventos externos (es decir, jms) o simplemente desea que su UI sea más interactiva (es decir, cree una lista de elementos y sea capaz de hacer otra cosa) deberías usar un hilo que no sea el hilo del evento awt (el swing principal). Entonces en estos casos genera un nuevo hilo y hace lo que debe hacer, y cuando los resultados finalmente vuelven, de alguna manera tiene que crear un evento que pueda ser ejecutado por awt / swing dispatcher. SwingWorker es un gran pequeño patrón de diseño que le permite hacer esto (de la otra manera es SwingUtilities). Es particularmente útil para buscar datos de fuentes externas o decir cálculos largos (representación de una escena de gráficos). Ayuda a automatizar el envío y la posterior reintegración de los resultados de un hilo externo (que no sea el hilo awt). Para eventos asíncronos (es decir, un evento de JMS necesita actualizar un resultado, use SwingUtilities).


Sí, puedes lograr lo que hace un SwingWorker con vanilla threads + invokeLater. SwingWorker proporciona una forma predecible e integrada para realizar tareas en un hilo de fondo e informar resultados en el EDT. SwingWorker también agrega soporte para resultados intermedios. De nuevo, puede hacer todo esto usted mismo, pero a veces es fácil usar la solución integrada y predecible, especialmente cuando se trata de simultaneidad.