Pregunta

Tengo una aplicación swing que almacena una lista de objetos. Cuando el usuario hace clic en un botón,

Quiero realizar dos operaciones en cada objeto en la lista, y luego una vez que se ha completado, gráfica los resultados en un JPanel. He estado tratando de SwingWorker, rescatable y Ejecutable para hacer el procesamiento, pero no importa lo que haga, al procesar la lista (que puede tomar hasta unos pocos minutos, ya que está obligado IO), la interfaz gráfica de usuario está bloqueada.

tengo la sensación de que es probablemente la forma en que estoy llamando a los hilos o algo, o podría ser que ver con la representación gráfica de funciones? Eso no está roscado, ya que es muy rápido.

Tengo que hacer las dos etapas de procesamiento con el fin también, así que ¿cuál es la mejor manera de asegurar que el segundo ha esperado en la primera? He usado join (), y luego

while(x.isAlive())  
{  
        Thread.sleep(1000);  
}

para tratar de asegurar esto, pero me preocupa que esto podría ser la causa de mi problema también.

He estado buscando por todas partes para algunas indicaciones, pero ya que no puedo encontrar ningún Estoy seguro de que estoy haciendo algo estúpido aquí.

¿Fue útil?

Solución

El problema es, su tarea de larga ejecución está bloqueando el hilo que mantiene la interfaz gráfica de respuesta.

Lo que tendrá que hacer es poner la tarea de larga ejecución en otro hilo.

Algunas formas comunes de hacer esto están utilizando temporizadores o un SwingWorker .

El tutoriales Java tienen mucha información con respecto a estas cosas en la lección de la concurrencia.

Para asegurarse de que la primera tarea termina antes de la segunda, sólo hay que poner los dos en el mismo hilo. De esa manera usted no tendrá que preocuparse de mantener dos hilos diferentes sincronizados correctamente.

Aquí hay un ejemplo de implementación de un SwingWorkerFor su caso:

public class YourTaskSwingWorkerSwingWorker extends SwingWorker<List<Object>, Void> {
    private List<Object> list
    public YourClassSwingWorker(List<Object> theOriginalList){
        list = theOriginalList;
    }

    @Override
    public List<Object> doInBackground() {
        // Do the first opperation on the list
        // Do the second opperation on the list

        return list;
    }

    @Override
    public void done() {
        // Update the GUI with the updated list.
    }
}

Para usar este código, cuando se dispara el evento para modificar la lista, cree un nuevo SwingWorker y decirle que empezar.

Otros consejos

No está devolviendo el hilo oscilación correctamente. Soy consciente de que está utilizando exigible / ejecutable pero supongo que no lo está haciendo bien (aunque no lo suficiente como Código Postal de saber con certeza).

La estructura básica sería:

swingMethod() { // Okay, this is a button callback, we now own the swing thread
    Thread t=new Thread(new ActuallyDoStuff());
    t.start();
}

public class ActuallyDoStuff() implements Runnable {
    public void run() {
        // this is where you actually do the work
    }
}

Esto es justo al lado de la parte superior de la cabeza, pero supongo que o bien no está haciendo el hilo.start y en lugar de llamar al método de ejecución directa, o está haciendo otra cosa en el primer método que los bloqueos hacia arriba (como Thread.Join). Ninguno de estos sería liberar el hilo swing. El primer método debe devolver rápidamente, el método run () puede tomar el tiempo que quiera.

Si usted está haciendo un Thread.Join en el primer método, a continuación, el hilo no está siendo devuelta al sistema!

Editar: (Segunda edición en realidad) Creo que hablar con el problema en realidad se está sintiendo - es posible que desee pensar más en términos de un sistema modelo / vista / controlador. El código que está escribiendo es el controlador (la vista está considerado generalmente como los componentes de la pantalla - vista / controlador suelen ser muy fuertemente)

.

Cuando el controlador recibe el evento, debe pasar el trabajo fuera de su modelo. La vista es entonces fuera de la foto. No espera para el modelo, que acaba de hacer.

Una vez finalizada su modelo, que necesita para luego decirle al controlador para hacer otra cosa. Lo hace a través de uno de los métodos de invocación. Esto transfiere el control al controlador y que van en su camino alegre. Si se piensa en ello de esta manera, la separación de control y deliberadamente pasando hacia atrás y adelante no se siente tan voluminosos, y de hecho es muy común que hacerlo de esta manera.

Parece que el problema podría ser que usted está esperando en las roscas para terminar desde el interior del hilo de interfaz gráfica de usuario. Su hilo de interfaz gráfica de usuario no debe esperar en estos temas, en lugar usted debe tener los subprocesos de trabajo invocan algún método en el subproceso de interfaz gráfica de usuario que establece un indicador. Cuando ambas banderas se establecen a continuación, usted sabe Terminaron los dos hilos y se puede hacer la gráfica.

Realmente no puedo hablar con el modelo de hilos de swing, pero:

  

Tengo que hacer las dos etapas de procesamiento con el fin también, así que ¿cuál es la mejor manera de asegurar que el segundo ha esperado en la primera?

En este tipo de funcionalidad, sugeriría a crear dos subprocesos de trabajo, e incrustar un agente de JMS. Entregar el trabajo a los dos hilos de la transmisión de mensajes en colas JMS que leer. Su hilo de interfaz gráfica de usuario es libre de examinar las colas para determinar cuando el trabajo está ocurriendo y representar la situación actual en la interfaz de usuario.

La solución a mi problema era una mezcla de jjnguy y respuestas de Bill K, así que muchas gracias por que los chicos. Necesitaba usar hilos dentro de un SwingWorker como esto:

public class Worker extends SwingWorker<Void, Void>   
{  
    private List<Object> list;  
    public YourClassSwingWorker(List<Object> theOriginalList){  
        list = theOriginalList;  
    }

    @Override
    public List<Object> doInBackground() {
        Thread t = new Thread(new ProcessorThread(list));  
        t.start();
    }

    @Override
    public void done() {
        // draw graph on GUI
    }
}  
class ProcessorThread implements Runnable {  
    //do lots of IO stuff  
    Thread t2 = new Thread(new SecondProcess());
    t2.start();  
}

Esto se aseguró de todo el trabajo que se está haciendo por los subprocesos de trabajo lejos de la interfaz gráfica de usuario, y también asegurar que la propia SwingWorker no estaba haciendo todo el trabajo, lo que podría haber sido un problema.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top