I am in a process of improving usability of a Swing application. I am trying to add SwingWorks to offload some of the DB and IO calls that were running in the EDT and thus locking up the user interface. It has worked for the most part with isolated tasks that have no dependency from other tasks.
My problem is that some DB calls are dependent on each other (Task2 must happen after Task1). For example say I have a Task1 that makes a DB call and updates a ComboBox and I have Task2 that makes a DB call and updates a JList, but Task2 needs the updates to the ComboBox. What I have is that Task2 dependents on Task1 DB calls (doInBackground()) and the updates to ComboBox being finished (done()) (so both need to be finished doInBackground and done). Is there a good way of solving this? What’s a good way to enable Task2 wait on Task1.doInBackground() and Task1.done() to finish.
You can do this a number of ways. One will enable you to continue to use SwingWorker. You can use a CountDownLatch. Pass the latch to both task 1 and task 2. In task 2's run method await
on the latch and when task 1 is complete call countDown
on the latch.
public class Task1 implements Runnable{
final CountDownLatchlatch;
public Task1 (CountDownLatchlatch latch){ this.latch = latch; }
public void run(){
//do work
latch.countDown();
}
}
public class Task2 implements Runnable{
final CountDownLatchlatch;
public Task2 (CountDownLatchlatch latch){ this.latch = latch; }
public void run(){
latch.await();
//do work
}
}
And using it would look like
CountDownLatch latch = new CountDownLatch(1);
Runnable task1 = new Task1(latch);
Runnable task2 = new Task2(latch);
//submit task1 and task2
The alternative would be to use ExecutorService
. Submit task1, get its corresponding Future, assign that to task2 and get()
on task1's future.