Поток отправки событий (EDT) - единственный поток, в котором безопасно читать или обновлять графический интерфейс.
Кнопка паузы должна устанавливать переменную включения / выключения в потоке отправки событий.
Длительная операция и цикл должны не находиться в EDT. (Цикл также не должен работать непрерывно, ничего не делая, кроме проверки переменной, или он может легко съесть весь ваш процессор. Если ему больше нечего делать, он должен проверить, а затем в течение некоторого времени вызывать Thread.sleep()
(скажем, 100 мс ).)
Если вы можете доказать, что для переменной вкл / выкл задано значение OFF, но, тем не менее, она всегда читается как ON, возможно, значение переменной не копируется из EDT в рабочий поток. Сделайте volatile
, или synchronize
доступ к нему, или используйте AtomicReference
, или прочитайте его в EDT, используя SwingUtilities.invokeAndWait()
.
SwingWorker
вероятно, - это самый простой путь, здесь. Реализуйте трудоемкую операцию и проверку включения / выключения в методе doInBackground()
, а обновление графического интерфейса - в методе done()
.
public enum State {
RUNNING, STOPPED
}
public class ThreadSafeStateModel {
private State state = State.STOPPED;
public synchronized void stop() {
state = State.STOPPED;
}
public synchronized void start() {
state = State.RUNNING;
}
public boolean isRunning() {
return state == State.RUNNING;
}
}
public class ExpensiveProcessWorker extends SwingWorker<Void, Void> {
private final ThreadSafeStateModel model;
public ExpensiveProcessWorker(ThreadSafeStateModel model) {
this.model = model;
}
@Override // Runs in background
protected Void doInBackground() throws Exception {
while (model.isRunning()) {
// do one iteration of something expensive
}
return null;
}
@Override // Runs in event dispatch thread
protected void done() {
// Update the GUI
}
}
public class StopButton extends JButton {
public StopButton(final ThreadSafeStateModel model) {
super(new AbstractAction("Stop") {
@Override
public void actionPerformed(ActionEvent e) {
model.stop();
}
});
}
}
public class StartButton extends JButton {
public StartButton(final ThreadSafeStateModel model) {
super(new AbstractAction("Start") {
@Override
public void actionPerformed(ActionEvent e) {
model.start();
new ExpensiveProcessWorker(model).execute();
}
});
}
}
(Многое можно сделать, чтобы убрать это в зависимости от реального приложения, но вы поняли.)