我有一个课程:
public class Test {
private static String name;
public static String getName() {
return name;
}
public static void setName(String name) {
Test.name = name;
}
public static void print() {
System.out.println(name);
}
}
在我的Spark驱动程序中,我设置了这样的名称并调用print()
命令:
public final class TestDriver{
public static void main(String[] args) throws Exception {
SparkConf sparkConf = new SparkConf().setAppName("TestApp");
// ...
// ...
Test.setName("TestName")
Test.print();
// ...
}
}
但是,我得到NullPointerException
。如何将值传递给全局变量并使用它?
答案 0 :(得分:22)
好的,基本上有两种方法可以将master知道的值传递给执行者:
在任何一种情况下都不需要使用静态变量。但是,如果您想在执行程序VM上提供静态值,则需要执行以下操作之一:
希望这有帮助!
P.S:至于你的异常:我只是没有在代码示例中看到它,我敢打赌它正在其他地方发生。
编辑以获得额外的说明:懒惰的解决方案只是Scala,没有涉及Spark ......
object MyStaticObject
{
lazy val MyStaticValue = {
// Call a database, read a file included in the Jar, do expensive initialization computation, etc
4
}
}
由于每个Executor都对应一个JVM,因此一旦加载了类,MyStaticObject
将被初始化。 lazy
关键字保证MyStaticValue
变量仅在第一次实际请求时初始化,并保持其值。
答案 1 :(得分:6)
您的驱动程序进程中的类副本不是执行程序中的副本。它们不在同一个ClassLoader
中,甚至不在同一个JVM中,甚至不在同一台机器上。在驱动程序上设置静态变量对其他副本没有任何作用,因此您可以远程找到它。
答案 2 :(得分:1)
我想添加另一种方法,只有当您有一些变量在运行时作为参数传递时,这种方法才有意义。
火花配置-> --conf "spark.executor.extraJavaOptions=-DcutomField=${value}"
和
当您需要转换中的数据时,可以致电System.getProperty("cutomField");
您可以找到更多详细信息here
注意:当我们有大量变量时,上面讨论的没有意义 。在这种情况下,我希望使用@Daniel Langdon的方法。
答案 3 :(得分:0)
我想在DanielL的答案中再加一点
当使用static关键字声明变量时,JVM将在类加载期间加载它,因此,如果您创建一个jar并设置Java / scala类中静态字段的初始值存储在jar中,则工作人员可以直接使用它。但是,如果您在驱动程序中更改了静态字段的值,则工作人员只能看到分配给Jar的初始值,而更改后的值将不会反映出来,因此您需要再次复制新的jar或需要手动将类复制到所有执行程序中