javafx:大量设置值时,标签值更新会导致错误

javafx:大量设置值时,标签值更新会导致错误,java,multithreading,javafx-8,Java,Multithreading,Javafx 8,我用JavaFXUI编写了一个java程序来显示事务的实时计数器, 许多线程需要将更新后的值写入单个标签,我的做法如下: 1 -“SothPo.No”是主类中的一个整型变量(不是FX控制器类本身,我们考虑它的名字“MainClass”)定义了这样的方式: public static Integer SOME_NUMBER; synchronized(SOME_NUMBER){ MainClass.SOME_NUMBER--; } synchronized(SOME_NUMBER){

我用JavaFXUI编写了一个java程序来显示事务的实时计数器, 许多线程需要将更新后的值写入单个标签,我的做法如下:

1 -“SothPo.No”是主类中的一个整型变量(不是FX控制器类本身,我们考虑它的名字“MainClass”)定义了这样的方式:

public static Integer SOME_NUMBER;
synchronized(SOME_NUMBER){
    MainClass.SOME_NUMBER--;
}
synchronized(SOME_NUMBER){
    MainClass.SOME_NUMBER++;
}
label.setText(String.valueOf(SOME_NUMBER));
2-许多线程通过以下方式更新“SOME_NUMBER”的值:

public static Integer SOME_NUMBER;
synchronized(SOME_NUMBER){
    MainClass.SOME_NUMBER--;
}
synchronized(SOME_NUMBER){
    MainClass.SOME_NUMBER++;
}
label.setText(String.valueOf(SOME_NUMBER));
3-最后,其他类别的结果如下所示:

public static Integer SOME_NUMBER;
synchronized(SOME_NUMBER){
    MainClass.SOME_NUMBER--;
}
synchronized(SOME_NUMBER){
    MainClass.SOME_NUMBER++;
}
label.setText(String.valueOf(SOME_NUMBER));
这些数字应该每秒更新一次,所以我不想使用
任务
在特定的时间间隔内更新我的视图,也不想使用
平台。稍后运行
,因为当你每秒有大约5-20个事务时,它会以相当大的延迟显示它们。。。 所以我想要一个安全的方法来实现这样的东西来满足我的需求,因为我当前的实现会导致这样的错误,我会删除ui更新,所有这些都会消失:

> java.lang.NullPointerException
    at com.sun.javafx.text.PrismTextLayout.createLine(Unknown Source)
    at com.sun.javafx.text.PrismTextLayout.layout(Unknown Source)
    at com.sun.javafx.text.PrismTextLayout.ensureLayout(Unknown Source)
    at com.sun.javafx.text.PrismTextLayout.getBounds(Unknown Source)
    at javafx.scene.text.Text.getLogicalBounds(Unknown Source)
    at javafx.scene.text.Text.getYRendering(Unknown Source)
是否有机会使用可观察值或类似的值?

如果您不想使用,只需稍加修改即可复制并粘贴,以使用与任务相同的技术(以下代码只是来自任务源的复制和粘贴)

如果您知道您的值是整数,那么您可能希望使用而不是

代码将为您提供一个消息属性,您可以尝试从任何线程(通过
updateMessage
API)更新该属性的值,尽管只有在JavaFX应用程序线程准备好处理该属性时才会进行更新。您还可以观察属性的更改,并安全地将JavaFXUI组件绑定到属性,因为您知道属性本身甚至只在JavaFX应用程序线程上更新过

/**
 * Used to send message updates in a thread-safe manner from the subclass
 * to the FX application thread. AtomicReference is used so as to coalesce
 * updates such that we don't flood the event queue.
 */
private AtomicReference<String> messageUpdate = new AtomicReference<>();

private final StringProperty message = new SimpleStringProperty(this, "message", "");
@Override public final String getMessage() { checkThread(); return message.get(); }
@Override public final ReadOnlyStringProperty messageProperty() { checkThread(); return message; }

/**
 * Updates the <code>message</code> property. Calls to updateMessage
 * are coalesced and run later on the FX application thread, so calls
 * to updateMessage, even from the FX Application thread, may not
 * necessarily result in immediate updates to this property, and
 * intermediate message values may be coalesced to save on event
 * notifications.
 * <p>
 *     <em>This method is safe to be called from any thread.</em>
 * </p>
 *
 * @param message the new message
 */
protected void updateMessage(String message) {
    if (isFxApplicationThread()) {
        this.message.set(message);
    } else {
        // As with the workDone, it might be that the background thread
        // will update this message quite frequently, and we need
        // to throttle the updates so as not to completely clobber
        // the event dispatching system.
        if (messageUpdate.getAndSet(message) == null) {
            runLater(new Runnable() {
                @Override public void run() {
                    final String message = messageUpdate.getAndSet(null);
                    Task.this.message.set(message);
                }
            });
        }
    }
}

private void checkThread() {
    if (started && !isFxApplicationThread()) {
        throw new IllegalStateException("Task must only be used from the FX Application Thread");
    }
}

您可以使用两个s(一个在GUI中,一个在逻辑中),双向绑定它们,并在您的生产代码中设置此
DoubleProperty
的值。@Turing85可以给我一个示例/代码片段吗?您可以找到解释JavaFX属性和绑定的教程。我建议不要将GUI组件绑定到值在JavaFX应用程序之外修改的属性线例如,策略可能会导致您的程序不一致地失败。