java - 将参数从父级传递给 public void run()

标签 java javafx runnable java-threads

我有 50% 的绝望:P。我尝试(一开始)从线程代码更新 GUI,并得到 NullException。阅读了一段时间后,我了解到线程淹没了 JavaFX 应用程序窗口,为了让我从线程更新 GUI,我需要使用以下代码:

Platform.runLater(new Runnable() {
            @Override public void run() {

            //Update UI here     
            for (int i=0; i<2000;i++)
                {
                 MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
                }

            }
        });

所以我确实使用了这段代码,它确实允许我编辑主类的 GUI。不过,我的问题很简单。 => 我从线程运行的这段代码位于 public void run() (我运行代码的线程的)内。它看起来像这样:

@Override
    public void run() {

    String tmpVar;

    ... (Some code)
    ... (Some code)
    ... (Some code)

        Platform.runLater(new Runnable() {
            @Override public void run() {

            //Update UI here     
            for (int i=0; i<2000;i++)
                {
                 MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
                }

            }
        });

    ... (Some code)
    ... (Some code)
    ... (Some code)
}

如何将参数从父级的 public void run() 传递到此参数? 例如,String tmpString(我想传递它)。

请注意,如果我在 public void run() 之外将其声明为静态(例如)=> 我运行了很多线程,因此更新静态变量可能并不总是准确的(因为很多线程会更新)它同时)

谢谢!

最佳答案

基本上,您需要考虑将参数传递给 Runnable 对象,而不是传递给 run() 方法。

如果将匿名类设置为内部类,就会变得非常清楚:

@Override
public void run() {

    String tmpVar;

    // ... (Some code)
    // ... (Some code)
    // ... (Some code)

        Platform.runLater(new Updater(tmpVar));

    // ... (Some code)
    // ... (Some code)
    // ... (Some code)
}

// ...

public static class Updater implements Runnable {

    private final String var ;

    public Updater(String var) {
        this.var = var ;
    }



    @Override 
    public void run() {

        // Access var here

        for (int i=0; i<2000;i++){
            MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
        }

    }
}

现在,如果 tmpVarfinal 或“有效地final1”,那么它将与您的匿名内部类一起使用,并且是基本上转换为与上面的内部类完全相同的东西(换句话说,匿名内部类获得一个隐式字段,该字段填充有最终变量的值):

@Override
public void run() {

    final String tmpVar = ...;

    // ... (Some code)
    // ... (Some code)
    // ... (Some code)

    Platform.runLater(new Runnable() {
        @Override public void run() {

        // access tmpVar here:

        for (int i=0; i<2000;i++)
            {
             MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
            }

        }
    });

    // ... (Some code)
    // ... (Some code)
    // ... (Some code)
}

语言设计者实际上可以使用非最终变量来完成这项工作,但认为结果会太困惑。会发生的情况是,它会被转换为上面看到的相同内部类:换句话说,tmpVar当前值将被隐式传递给匿名内部类。这将是一个全新的变量,具有与您正在访问的变量不同的范围,并且其值将是匿名内部类时 tmpVar 值的“快照”被 build 。看似一个变量实际上引用了两个不同的变量可能具有不同的值被认为太困惑且容易出现错误。

但是,如果tmpVar不是最终的(或实际上最终的):即您要多次为其赋值,您可以显式“快照”变量:

@Override
public void run() {

    String tmpVar ;

    // ... (Some code)
    // ... (Some code)
    // ... (Some code)

    final String varCopy = tmpVar ;

    Platform.runLater(new Runnable() {
        @Override public void run() {

        // access varCopy here:

        for (int i=0; i<2000;i++)
            {
             MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
            }

        }
    });

    // ... (Some code)
    // ... (Some code)
    // ... (Some code)
}

(1) “有效最终”意味着变量仅被赋值一次。同样,这意味着您可以将其声明为final,而不会产生任何编译错误。

关于java - 将参数从父级传递给 public void run(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43119677/

相关文章:

Java:如何检查字段是否为 java.util.Collection 类型

java - 如何在Java中的mongojack中使用elemmatch

java - 使用目录路径创建新类型 "File"对象时出现无效 URL/非法参数异常

JavaFX:创建垂直菜单功能区

java - 从可运行/TimerTask 中检索字符串

java - 如何将程序链接到 Controller 类

java - 如何让 Talend 进程正确捕获 SIGINT?

JavaFX 2.2 javadoc?

Java - SWT - 单击提交按钮后可运行新的

java - 在 run() 方法中使用 return 会发生什么?