Pregunta

Tengo una pequeña aplicación de procesamiento de imágenes que hace varias cosas a la vez utilizando SwingWorker. Sin embargo, si se me acaba el siguiente código (extracto simplificado), simplemente se cuelga en JDK 7 B70 (ventanas), pero trabaja en 6u16. Se inicia un nuevo trabajador a otro trabajador y espera a que su resultado (la aplicación real, se ejecuta múltiples sub-trabajadores y espera a que todo este camino). ¿Usé algunos patrones erróneos aquí (en su mayoría no es de 3-5 trabajadores de la SwingWorker-piscina, que tiene un límite de 10 creo)?

import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Swing {
       static SwingWorker<String, Void> getWorker2() {
               return new SwingWorker<String, Void>() {
                       @Override
                       protected String doInBackground() throws Exception {
                               return "Hello World";
                       }
               };
       }
       static void runWorker() {
               SwingWorker<String, Void> worker 
                   = new SwingWorker<String, Void>() {
                       @Override
                       protected String doInBackground() throws Exception {
                               SwingWorker<String, Void> sw2 = getWorker2();
                               sw2.execute();
                               return sw2.get();
                       }
               };
               worker.execute();
               try {
                       System.out.println(worker.get());
               } catch (Exception e) {
                       e.printStackTrace();
               }
       }
       public static void main(String[] args) {
               SwingUtilities.invokeLater(new Runnable() {
                       @Override
                       public void run() {
                               runWorker();
                       }
               });
       }

}
¿Fue útil?

Solución

Como nadie ha disparado el enlace sin embargo, parece que este es en realidad un error conocido:

http://bugs.sun.com/bugdatabase/view_bug.do? bug_id = 6880336

Sorprendentemente hay menos de 100 votos a favor de lo que debería ser un error sensacional para la mayoría de las aplicaciones no triviales.

Otros consejos

Sus SwingWorkers se ejecutan en su rosca SwingWorker. Así que cuando ves

  

Parece que cuelga en sw2.get () y sólo hay un hilo llamado swingworker- en JDK7. En jdk6, veo 3-5 a la vez. - kd304

Esto se debe a la clase SwingWorker no es un hilo, pero una tarea que se ejecuta en un hilo, y la configuración por defecto para el ExecutorService para SwingWorker en Java 6 está configurado diferente de la que en Java 7. IE su SwingWorkerExecutorService ( que se define dentro de la clase SwingWorker) tiene un valor diferente para el número máximo de hilos para asignar a las tareas.

//From Java 6 SwingWorker

private static final int MAX_WORKER_THREADS = 10;

public final void execute() {
    getWorkersExecutorService().execute(this);
}

private static synchronized ExecutorService getWorkersExecutorService() {
...
private static synchronized ExecutorService getWorkersExecutorService() {
new ThreadPoolExecutor(0, MAX_WORKER_THREADS,
                                     1L, TimeUnit.SECONDS,
                                     new LinkedBlockingQueue<Runnable>(),
                                     threadFactory)
}

Sólo hay un hilo conductor a las tareas SwingWorker, y que la primera tarea está esperando la finalización de la segunda tarea, que no se puede ejecutar, porque el hilo de la segunda tarea se ejecuta en espera la segunda tareas para completar antes de que volverá. Decisiones sobre el hilo SwingWorker depende de la ejecución de otro es un camino seguro a un punto muerto. Es posible que desee buscar en el uso de una ExecutorService para programar eventos para ser ejecutado en el hilo SwingWorker, y no condicionan un evento programado en la terminación de otro evento programado.

  

Java 7 SwingWorker

Si examina el código fuente para SwingWorker, se ve como un ExecutorService está siendo utilizada como un grupo de subprocesos de trabajo. Es posible que el tipo de ExecutorService utilizado ha cambiado entre Java y Java 6 7. Parece que el código será un punto muerto si el ExecutorService sólo logra exactamente 1 hilo a la vez (como se parecen tener notado).

Esto es porque su 'sw2.get) (' llamada se bloqueará el subproceso actual, que es el mismo hilo de los sw2 tratarán de usar. sw2 nunca se puede ejecutar debido a que el primer trabajador está bloqueando.

Creo que la mejor solución es cambiar la lógica de modo que no se llama a los trabajadores cadenas de oscilación como este.

Antes de la actualización JDK 18 podría ejecutar:

public static void main(String[] args) {

    new SwingWorker<Void, Void>() {
        @Override
        protected Void doInBackground() throws Exception {
            System.out.println("ok");
            return null;
        }
    }.execute();

}

Este código no funciona más, simplemente porque SwingWorkers deben ser ejecutados en EDT.

Por lo tanto, no se puede SwingWorkers nido (SW2 va nunca se queda en ti código de ejemplo en las nuevas JDK).

supongo que la sustitución de swingWorkers anidadas con ExecutorService java.util.concurrent.Future llama es una buena solución.

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