Решение Алекса работает нормально, но если вы все еще хотите использовать более низкий уровень управления потоками (wait-notify), вот как вы можете это сделать:
public class WebsiteOverviewController {
@FXML
public void handleScanInbox() {
isScanning.set(true);
thread = new Thread(mainApp::handleScanInbox);
thread.start();
}
@FXML
public void handlePauseScanInbox() {
isScanning.set(false);
mainApp.pause();
}
// Another handler for resuming...
}
public class MainApp {
private final AtomicBoolean paused = new AtomicBoolean(false);
public void handleScanInbox() {
for (int i = 0; i < numberOfItems; i++) { // This could be a while loop
synchronized (paused) {
while (paused.get()) { // Using while so that it could re-wait in the case that the object was falsely notified
try {
pause.wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Do whatever you need to do
}
}
public void pause() {
pause.compareAndSet(false, true);
}
public void resume() {
synchronized (paused) {
if (paused.get()) {
paused.set(false);
paused.notify();
}
}
}
}
Обновление
Если вы хотите иметь возможность вызывать конкретный объект для переключения между приостановкой и возобновлением, вы можете добавить для этого другой метод:
// In MainApp
public void togglePauseResume() {
synchronized (paused) {
if (paused.get()) {
paused.set(false);
paused.notify();
}
else {
paused.set(true); // You don't need compareAndSet() because paused object has been used for synchronization (i.e. locked)
}
}
}
В любом случае вам следует попытаться избежать этого:
@FXML
public void handleButton() {
if (mainApp.isPaused()) { // You added a getter for paused
mainApp.pause();
}
else {
mainApp.resume();
}
}
Это потому, что MainApp.paused
может потенциально меняться между геттером и pause()
(то есть, состояние гонки).
Обновление 2
Если вы просто хотите использоватьединственный метод для запуска / возобновления потока, вы можете просто создать поток, если он null
, или вызвать resume()
в противном случае.
@FXML
public void handleScanInbox() {
isScanning.set(true); // Not sure if you still need this
if (thread == null) {
thread = new Thread(mainApp::handleScanInbox);
thread.start();
}
else if (thread.isAlive()) {
mainApp.resume();
}
}
Я также изменил if (paused.get())
на while (paused.get())
В случае, если notify()
был вызван paused
случайно.