【发布时间】:2020-10-10 09:43:00
【问题描述】:
基本上,线程 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();
}
}
现在 - 当舞台有 showAndWait() 函数时,为什么我要自己锁定它?因为这也不起作用,而且它最终会暂停 FX 线程而不是创建线程,因为 show() 和 showAndWait() 都必须在 FX 线程上发生。
我的输出如下:
. . .
ShortcutManager State: Waiting for user...
Waiting.
Closing and notifying.
Notified.
然后仅此而已。不打印结果;线程没有其他工作。我的 FX 线程和其他工作线程运行良好,但这个似乎只是终止,即使还有更多工作要做。
附:在你批评我之前,我在打算保留它们的地方使用 Loggers,而当我打算删除它们时使用 System.out。
【问题讨论】:
-
我不是 JavaFX 专家,但您的方法听起来很危险。您通常会这样做的方式是创建一些其他线程来完成工作,当线程完成时,您会告诉 UI 线程 repaint() (在 Swing repaint() 中是线程安全的)。 paint() 方法会注意到您的工作已准备就绪,并执行适当的 UI 操作以使事情变得漂亮。
-
还有其他方法。就像使用某种 util.concurrent Queue 一样。您有一个线程添加到该队列,并且 UI 线程检查该队列。我认为这种方法通常是可取的。使用 wait() 和 notify() 和 synchronized 使用了太多的低级原语,很可能会出现一些细微的错误。首选来自 util.concurrent 的构造。
-
无法重现该问题(当然我需要更改一些内容,例如修复语法错误以编译代码)。请注意,您可以使用
Platfrom.runLater从 javafx 应用程序线程中轻松检索信息以检索数据,然后使用该信息填充您在后台线程上创建的CompletableFuture。例如,请参阅我的帖子:stackoverflow.com/a/58761795/2991525 -
使用更高级别的 API 进行线程处理总是比尝试使用线程原语重现相同的功能要好。 @fabian 提供的示例就是一个很好的例子;另见stackoverflow.com/questions/14941084/…
标签: java multithreading javafx