Функция продолжается после notifyAll (), но поток завершается после возврата из функции - PullRequest
0 голосов
/ 20 июня 2020

В основном, поток A wait () для объекта блокировки, затем поток B notifyAll (). Функция в потоке A завершается, но не возвращается для нормальной работы.

Следует отметить, что я использую 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();
    }

}

Теперь - почему я сам блокирую его, если в Stage есть функция showAndWait ()? Потому что это тоже не сработало, плюс в итоге он приостанавливает поток FX вместо потока создания, поскольку в потоке FX должны выполняться и show (), и showAndWait ().

Мой вывод выглядит следующим образом:

. . .

ShortcutManager State: Waiting for user...
Waiting.
Closing and notifying.
Notified.

И больше ничего. Нет печати результата; никакая другая работа не выполняется потоком. Мой поток FX и другие рабочие потоки работают нормально, но этот, похоже, просто завершается, хотя еще многое предстоит сделать.

PS Прежде чем вы меня критикуете, я использую регистраторы, где я намерен их сохранить и System.out, когда я собираюсь их удалить.

1 Ответ

0 голосов
/ 23 июня 2020

Во-первых - спасибо тем полезным людям, которые прокомментировали. Хотя ваши решения не сработали для меня, они указали мне правильное направление.

Теперь мое решение: я просто обернул всплывающий результат, заблокировал и c в 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);
        });
    }
    
    ----
    
}

Работает совершенно надежно. По какой-то причине наличие CompletableFuture для самого объекта никогда не запускает функцию whenComplete, даже если будущее предположительно "завершено".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...