簡體   English   中英

Function 在 notifyAll() 后繼續,但在 function 返回后線程終止

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM