2011-09-25 13 views
11

Mi computadora tiene 4 núcleos y estoy ejecutando un programa Java gui de oscilación. Cuando ejecuto mi aplicación, solo utiliza dos núcleos y aproximadamente el 30% de utilización de la CPU. Tengo una gran cantidad de archivos para procesar y quiero dividirlos en dos hilos para hacer esta tarea más rápido usando más cpu.Instancias de Swingworker que no se ejecutan al mismo tiempo

tengo una clase SwingWorker llamada PrepareTask, que tiene un constructor con dos enteros:

class PrepareTask extends SwingWorker<Void, Void> { 
    int start, end; 
    PrepareTask (int start, int end) { ... } 
    ... 
    public Void doInBackground() {... } 
    public void done() { ... } 

puedo crear dos instancias de este como:

PrepareTask prepareTask = new PrepareTask(0,numberOfFiles/2); 
    prepareTask.execute(); 
    PrepareTask prepareTask2 = new PrepareTask(numberOfFiles/2, numberOfFiles); 
    prepareTask2.execute(); 

Ambos se lanzaron (parece), pero cuando se ejecuta, puedo ver (imprimir stmts) que la primera preparación tiene que terminar (imprima stmts dentro) antes de que comience la segunda. Y la utilización de la CPU es la misma que antes, alrededor del 30%. Ambos, por supuesto, toman datos de la misma fuente, un DefaultTableModel.

¿Alguna idea sobre cómo hacer esto o lo que estoy haciendo mal? gracias.

+0

Tenga en cuenta que si la mayor parte del tiempo de procesamiento implica acceso a archivos, entonces tener muchos hilos no necesariamente lo hará más rápido porque el disco se convertirá en su cuello de botella. ¿Puede desarrollar aún más el tipo de procesamiento que realiza en estos archivos? – jfpoilpret

Respuesta

16

Esto es el resultado de un cambio en el comportamiento de SwingWorker de una actualización de Java 6 a otra. De hecho, hay un informe de error al respecto en la antigua base de datos de errores de SUN para Java 6.

Lo que sucedió fue que SUN cambió la implementación original de SwingWorker del uso de N hilos a usar 1 hilo con una cola sin límites. Por lo tanto, no puede tener dos SwingWorkers funcionando al mismo tiempo. (Esto también crea un escenario donde puede ocurrir un punto muerto: si un columpio espera a otro que espera el primero, una tarea podría entrar en un punto muerto como resultado.)

Lo que puede hacer para evitar esto es utilizar un ExecutorService y publicar FutureTasks en él. Estos proporcionarán el 99% de la API de SwingWorker (SwingWorker es un derivado FutureTask), todo lo que tienes que hacer es configurar tu Executor correctamente.

+1

He visto esto antes, pero lo ha resumido mejor que la mayoría: +1 –

+0

Y esto debería solucionarse en Java SE 6u21: http://www.oracle.com/technetwork/java/javase/bugfixes6u21- 156339.html – keuleJ

+0

Este es el error: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6925575 – keuleJ

0

¿Tal vez Swing está controlando la programación de sus hilos? O tal vez SwingWorker tiene un tamaño de grupo de subprocesos de 1 (no hay ninguna descripción en SwingWorker javadoc sobre la ejecución de múltiples subprocesos de SwingWorker y supongo que varios subprocesos podrían causar algunos problemas de concurrencia difíciles en Swing).

Si todo lo que quiere hacer es ejecutar algún tipo de procesamiento en paralelo, Se puede resolver esto de la manera sencilla mediante la extensión de la Thread clase Java, la aplicación de run, llamando SwingUtilities.invokeLater() en el fin de actualizar la interfaz gráfica de usuario con los cambios:

class PrepareTask extends Thread 
    { 
     PrepareTask (int start, int end) { ... } 
     public void run() { ... ; SwingUtilities.invokeLater(new Runnable() { public void run() { do any GUI updates here })} 

empezar las discusiones con:

prepareTask.start(); 

O tal vez algo en su modelo de datos es solo thre aded y bloqueando el segundo hilo? En ese caso, debe resolver ese problema con el modelo de datos.

Cuestiones relacionadas