开发者

Swingworker instances not running concurrently

My computer has 4 cores and I am running a Java swing gui program. When I run my application it only uses two cores and about 30% CPU utilization. I have a large number of files to process and want to split them up into two threads to get this task done faster using more cpu.

I have a SwingWorker class called PrepareTask, that has a constructor with two ints:

class PrepareTask extends SwingWorker<Void, Void> {
  int start, en开发者_如何学编程d;
  PrepareTask (int start, int end) { ... }
  ...
    public Void doInBackground() {... }
    public void done() { ... }

I create two instances of this like:

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

Both are launched (it appears) but when it runs I can see (print stmts) that the first prepare has to finish (print stmts inside) before the second one starts. And the CPU utilization is the same as before, about 30%. They both of course grab data from the same source, a DefaultTableModel.

Any ideas on how to do this or what I am doing wrong? thanks.


This is the result of a change in SwingWorker behaviour from one Java 6 update to another. There's actually a bug report about it in the old SUN bug database for Java 6.

What happened was SUN changed the original SwingWorker implementation from using N threads, to using 1 thread with an unbounded queue. Therefore you cannot have two SwingWorkers run concurrently anymore. (This also creates a scenario where deadlock may occur: if one swingworker waits for another which waits for the first, one task might enter a deadlock as a result.)

What you can do to get around this is use an ExecutorService and post FutureTasks on it. These will provide 99% of the SwingWorker API (SwingWorker is a FutureTask derivative), all you have to do is set up your Executor properly.


Maybe Swing is controlling the scheduling of your threads? Or maybe SwingWorker has a thread pool size of 1 (there is no description in SwingWorker javadoc about running multiple SwingWorker threads and I guess multiple threads could cause some difficult concurrency problems in Swing).

If all you want to do is run some processing in parallel, can you solve this the simple way by extending the Java Thread class, implementing run, calling SwingUtilities.invokeLater() at the end to update the GUI with any changes:

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

start the threads with:

    prepareTask.start();

Or maybe something in your data model is single-threaded and blocking the second thread? In that case, you have to solve that problem with the data model.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜