Запустите другой поток после завершения SwingWorker в Java

Я знаю, что есть много вопросов по SO, но ни один из них не дает достаточно хорошего ответа, и прежде чем задавать вопросы, я специально гуглил SO, но ничто не могло прояснить это. Я просто хочу начать другой поток, когда мой SwingWorker закончит свою работу.

Я хочу запустить таймер, когда SwingWorker заканчивает свою работу, но не могу понять, как это сделать.

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();

Теперь есть еще один поток startTimer, который я хочу запустить, когда закончится этот SwingWork.

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

Но я не понимаю, как я могу это сделать?

2 ответа

Решение

Если я что-то упустил, вы можете передать ссылку в конструкторе createGUI и начать, когда 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();
  }
}

Вам также необходимо изменить

new createGUI().execute();

что-то вроде

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

Кроме того, имена классов должны начинаться с заглавной буквы. CreateGUI а также StartTimer

Примечание: в ответе Эллиота нет ничего плохого, ожидайте, что он связывает рабочий процесс с работником и передает ссылки на объект работнику, которые в противном случае не потребовались бы (+1 к его ответу)

В качестве альтернативы передаче ссылок на классы, которые, вероятно, не должны знать или заботиться о таких вещах, вы можете использовать SwingWorkers PropertyChangeListener служба поддержки.

Это разъединяет работника и делает его более пригодным для повторного использования...

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();

Который просто побежит...

public class CreateGUI extends SwingWorker<Integer, Integer> {

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

Как примечание (как меня раздражает имя рабочего), Swing НЕ является потокобезопасным, вы не должны создавать или изменять элементы пользовательского интерфейса вне потока диспетчеризации событий...

Обновление...

Если все, что вы хотите сделать, это выполнить цепочку выполнения ваших потоков, то вы можете использовать однопоточный ExecutorService, например...

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

es.shutdown();

Это гарантирует, что StartTimer не может бежать, пока CreateGUI или заканчивает или терпит неудачу...

Другие вопросы по тегам