JDK-6925575 : SwingWorker misuses ThreadPoolExecutor, only runs one task at a time, MAX_WORKER_THREADS ignored
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2010-02-11
  • Updated: 2011-01-19
  • Resolved: 2010-02-11
Related Reports
Duplicate :  
Run the following on JDK 6u19:

import java.util.concurrent.CountDownLatch;
import javax.swing.SwingWorker;
public class Demo {
    public static void main(String[] args) throws Exception {
        int cnt = 20;
        final CountDownLatch latch = new CountDownLatch(cnt);
        for (int i = 0; i < cnt; i++) {
            final int count = i;
            new SwingWorker<Void,Void>() {
                protected Void doInBackground() throws Exception {
                    System.out.printf("Started %d on thread %s\n", count, Thread.currentThread().getName());
                    System.out.printf("Finishing %d on thread %s\n", count, Thread.currentThread().getName());
                    return null;
                protected @Override void done() {
                    System.out.printf("Done %d on thread %s\n", count, Thread.currentThread().getName());
    private Demo() {}

You might expect a bunch of interleaved jobs, with #1 - #10 (SwingWorker.MAX_WORKER_THREADS = 10) starting, then some finishing, others starting, and finally #11 - #20 finishing. Instead you see

Started 0 on thread SwingWorker-pool-1-thread-1
Finishing 0 on thread SwingWorker-pool-1-thread-1
Started 1 on thread SwingWorker-pool-1-thread-1
Done 0 on thread AWT-EventQueue-0
Finishing 1 on thread SwingWorker-pool-1-thread-1
Started 2 on thread SwingWorker-pool-1-thread-1
Done 1 on thread AWT-EventQueue-0
Finishing 18 on thread SwingWorker-pool-1-thread-1
Started 19 on thread SwingWorker-pool-1-thread-1
Done 18 on thread AWT-EventQueue-0
Finishing 19 on thread SwingWorker-pool-1-thread-1
Done 19 on thread AWT-EventQueue-0

i.e. only one job is run at a time! The reason seems to be that getWorkersExecutorService seems to ignore this note from ThreadPoolExecutor's Javadoc:

"Using an unbounded queue (for example a LinkedBlockingQueue without a predefined capacity) will cause new tasks to wait in the queue when all corePoolSize threads are busy. Thus, no more than corePoolSize threads will ever be created. (And the value of the maximumPoolSize therefore doesn't have any effect.)"

EVALUATION We haven't decided yet whether it's a bug or not (as the exact threading implementation of SwingWorker is not specified), but it's definitely what we'd like to fix. Duplicate of 6880336. Suggested fix - increase the core pool size to MAX_WORKER_THREADS - should certainly work, but it seems to be too straightforward. Probably, there's more elegant solution.

PUBLIC COMMENTS Problem discovered thanks to Michael Franz: http://netbeans.org/projects/platform/lists/dev/archive/2010-02/message/350

WORK AROUND Do not use SwingWorker.execute(); create your own ExecutorService and submit jobs to it.

SUGGESTED FIX diff --git a/src/share/classes/javax/swing/SwingWorker.java b/src/share/classes/javax/swing/SwingWorker.java --- a/src/share/classes/javax/swing/SwingWorker.java +++ b/src/share/classes/javax/swing/SwingWorker.java @@ -772,7 +772,7 @@ }; executorService = - new ThreadPoolExecutor(1, MAX_WORKER_THREADS, + new ThreadPoolExecutor(MAX_WORKER_THREADS, MAX_WORKER_THREADS, 10L, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(), threadFactory);