有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

hadoop中的java瞬态变量和静态方法,dev寻求启示

我在看hadoop框架中的生产代码,这是没有意义的。为什么我们要使用瞬态方法,为什么我不能将实用方法设为静态方法(领导告诉我不要将isThinger设为静态方法)?我查找了transient关键字,它与序列化有关。这里真的使用序列化吗

//extending from MapReduceBase is a requirement of hadoop
public static class MyMapper extends MapReduceBase {

    // why the use of transient keyword here?
    transient Utility utility;

    public void configure(JobConf job) {

        String test = job.get("key");

        // seems silly that we have to create Utility instance.
        // can't we use a static method instead?
        utility = new Utility();

        boolean res = utility.isThinger(test);

        foo (res);
    }

    void foo (boolean a) { }
}


public class Utility {
   final String stringToSearchFor = "ineverchange";

   // it seems we could make this static.  Why can't we?
   public boolean isThinger(String word) {
      boolean val = false;
      if (word.indexOf(stringToSearchFor) > 0) {
           val = true;
      }
      return val;
   }
}

共 (2) 个答案

  1. # 1 楼答案

    除非这里没有显示某些内容,否则我怀疑制作Utility一个static方法在很大程度上取决于风格。特别是,如果您没有注入Utility实例,而不是在内部按需实例化它,那么它是毫无意义的。正如所写的,它不能被重写,也不能比static方法更容易测试

    至于transient,你是对的,它是不必要的。如果最初的开发人员在继承或实现链的某个地方使用序列化,并且他们通过将不可序列化的实例变量标记为transient来避免编译器警告,我不会感到惊讶

  2. # 2 楼答案

    代码中的问题是本地模式(开发和测试用例通常使用它)和分布式模式之间的差异

    在本地模式下,所有内容都将在单个JVM中,因此您可以安全地假设,如果您更改了一个静态变量(或共享某个状态的静态方法,在您的情况下stringToSearchFor),那么对于每个输入块的计算,更改都是可见的

    在分布式模式下,每个块都在自己的JVM中处理。因此,如果您更改状态(例如在stringToSearchFor),这对于在其他主机/JVM/任务上运行的所有其他进程都不可见

    这种不一致性导致在编写map/reduce函数时遵循以下设计原则:

    1. 尽量保持无国籍
    2. 如果您需要状态(例如可变类),从不在map/reduce类static中声明引用(否则它在测试/开发时的行为将不同于在生产中)
    3. 不可变常量(例如配置键String)应该定义为staticfinal

    Hadoop中的transient非常无用,Hadoop没有序列化usercode(Mapper/Reducer)类/对象中的任何内容。只有当对Java序列化做一些我们不知道的事情时,这才是一个问题

    对于您的案例,如果Utility确实是一个实用程序,并且stringToSearchFor是一个不可变常量(因此永远不会更改),那么您可以安全地将isThinger声明为static。如果您没有对MapReduceBase进行任何Java序列化,请删除该transient