[英]Function continues after notifyAll(), but Thread terminates after function returns
基本上,線程 A wait() 鎖定 object,然后是線程 B notifyAll()。 線程 A 上的 function 完成,但不會返回正常操作。
值得注意的是,我使用的是 JavaFX。 為了使我的 FX 線程與我的工作線程分開,我創建了一個新線程以防止在我鎖定它時出現問題等。
這是我的代碼(簡化為有問題的函數):
public class ShortcutManager {
private static final StringProperty STATE = new SimpleStringProperty("Create Shortcut");
public static void create() {
Thread creationThread = new Thread(() -> {
// Do some work (sends logs to the logger)
String result = prompt();
if (result != null) {
// Do more work (sends logs to the logger)
} else {
// Do other work (sends logs to the logger)
}
}
creationThread.start();
}
private static String prompt() {
STATE.setValue("Waiting for user...");
String result = popup.showAndWait();
System.out.println("Result: \"" + result + "\"");
return result;
}
public class CmlPopup implements Initializable {
private boolean isClosed = false;
public synchronized String showAndWait() {
isClosed = false;
Platform.runLater(() -> {
stage.show();
});
while (!isClosed) {
try {
System.out.println("Waiting.");
wait();
System.out.println("Notified.");
} catch (InterruptedException ex) {
}
}
return getResult();
}
public synchronized void close() {
stage.close();
isClosed = true;
System.out.println("Closing and notifying");
notifyAll();
}
}
現在 - 當舞台有 showAndWait() function 時,為什么我要自己鎖定它? 因為那也不起作用,而且它最終會暫停 FX 線程而不是創建線程,因為 show() 和 showAndWait() 都必須在 FX 線程上發生。
我的output如下:
. . .
ShortcutManager State: Waiting for user...
Waiting.
Closing and notifying.
Notified.
然后僅此而已。 不打印結果; 線程沒有其他工作。 我的 FX 線程和其他工作線程運行良好,但這個似乎只是終止,即使還有更多工作要做。
PS 在你批評我之前,我在打算保留它們的地方使用 Loggers,當我打算刪除它們時使用 System.out。
首先-感謝那些評論的樂於助人的人。 盡管您的解決方案對我不起作用,但它們為我指明了正確的方向。
現在,我的解決方案:我只是將彈出結果、阻塞等包裝在 CompletableFuture 中。
public class CmlPopup<R, D> implements Initializable {
private final Object closeLock = new Object();
private volatile boolean isClosed = false;
----
public CompletableFuture<R> showAndGet() {
Platform.runLater(() -> {
stage.show();
});
return CompletableFuture.supplyAsync(() -> {
synchronized (closeLock) {
while (!isClosed) {
try {
closeLock.wait();
} catch (InterruptedException ex) {
}
}
return contentManager.getResult();
}
}
public void showThenRun(BiConsumer<? super R, ? super Throwable> action) {
CompletableFuture.supplyAsync(() -> {
synchronized (closeLock) {
while (!isClosed) {
try {
closeLock.wait();
} catch (InterruptedException ex) {
}
}
return contentManager.getResult();
}
}).whenComplete(action);
Platform.runLater(() -> {
stage.show();
});
}
public void close() {
stage.close();
synchronized (closeLock) {
isClosed = true;
closeLock.notifyAll();
}
}
}
public class ShortcutManager {
private static final CmlPopup<String, Integer> POPUP = new CmlPopup(...);
----
private static void prompt(File userData) {
POPUP.showThenRun((String result, Throwable ex) -> {
System.out.println("Result: \"" + result+ "\"");
ShortcutManager.identifyAndGridImages(result, userData);
});
}
----
}
這完全可靠。 無論出於何種原因,為 object 本身擁有 CompletableFuture 永遠不會運行 whenComplete function,即使未來也被認為是“完整的”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.