user4099884
user4099884

Reputation:

Start another thread after SwingWorker completes in Java

I know there many questions on SO but non of them has good enough answer and before asking here I googled a lot specially SO but nothing could make it clear. I just simply wants to start my other thread when my SwingWorker finish its work.

I want to start a timer when the SwingWorker finishes it's work but cannot figure out how.

class createGUI extends SwingWorker<Void, Void>
{
    @Override
    protected Integer doInBackground() throws Exception
    {
         //Some long processing
    }

    @Override
    protected void done()
    {
         //Doing GUI work here
         prgBar.setInderminent(false);
    }
}

//Starts a progressBar and calls createGUI();
prgBar.setInderminent(true);
new createGUI().execute();

Now there is another startTimer Thread which I want to start when this SwingWork finishes.

public class startTimer implements Runnable
{
     @Override
     public void run()
     {
         while(true)
         {
             Thread.sleep(1000);
             //Update Database
         }
     }
}

But I don't understand how can I do so?

Upvotes: 1

Views: 624

Answers (2)

MadProgrammer
MadProgrammer

Reputation: 347204

Note: There is nothing wrong with Elliot's answer, expect that it couples the work flow to the worker and passes object references to the worker, which it would otherwise not require (+1 to his answer)

As an alternative to passing about references to classes which probably don't need to know or care about such things, you could use the SwingWorkers PropertyChangeListener support.

This decouples the worker and makes it more reusable...

CreateGUI worker = new CreateGUI();
worker.addPropertyChangeListener(new PropertyChangeListener() {
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if ("state".equals(evt.getPropertyName())) {
            SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue();
            switch (state) {
                case DONE:
                    prgBar.setInderminent(false);
                    startTimer.start();
                    break;
            }
        }
    }
});
worker.execute();

Which would simply run...

public class CreateGUI extends SwingWorker<Integer, Integer> {

    @Override
    protected Integer doInBackground() throws Exception {
        // Working hard or hardly working...
        return ???;
    }
}

Just as a side note (as the worker name freaks me out), Swing is NOT thread safe, you should not create or modify UI elements from outside the Event Dispatching Thread...

Updated...

If all you want to do is chain the execution of your threads, then you could use a single threaded ExecutorService, for example...

ExecutorService es = Executors.newSingleThreadExecutor();
es.submit(new CreateGUI());
es.submit(new StartTimer());

es.shutdown();

This ensures that StartTimer can't run until CreateGUI either finishes or fails...

Upvotes: 1

Elliott Frisch
Elliott Frisch

Reputation: 201447

Unless I'm missing something, you could pass a reference in the constructor to createGUI and start that when done().

class createGUI extends SwingWorker<Void, Void>
{
  private Thread startTimer;
  public createGUI(Thread startTimer) {
    this.startTimer = startTimer;
  }
  @Override
  protected Integer doInBackground() throws Exception {
     //Some long processing
  }

  @Override
  protected void done()
  {
     //Doing GUI work here
     prgBar.setInderminent(false);
     startTimer.start();
  }
}

You would also need to change

new createGUI().execute();

to something like

new createGUI(new Thread(new startTimer())).execute();

Also, class names should start with a capital letter. CreateGUI and StartTimer

Upvotes: 3

Related Questions