Alex的解决方案工作正常,但如果您仍想使用较低级别的线程管理(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 可能会在getter和 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 .