我正在看hadoop框架中的产品代码,这是没有意义的。为什么我们要使用transient,为什么我不能使实用方法成为静态方法(领导告诉我不要使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条答案
按热度按时间vm0i2vca1#
除非这里没有显示什么,否则我怀疑
Utility
一static
方法主要归结为风格。特别是,如果你没有注射Utility
示例而不是按需在其中示例化,那么它就毫无意义了。正如它所写的那样,它不能被重写,也不能比以前更容易地被测试static
方法。至于
transient
,你是对的,这是不必要的。如果最初的开发人员在继承或实现链的某个地方使用序列化,并且他们通过将不可序列化的示例变量标记为transient
.w8biq8rn2#
代码中的问题是本地模式(dev&testcases通常使用它)和分布式模式之间的差异。
在本地模式下,所有内容都将在一个jvm中,因此您可以安全地假设,如果您更改了一个静态变量(或者在您的情况下更改了一个共享某些状态的静态方法)
stringToSearchFor
)对于每个输入块的计算,这种变化都是可见的。在分布式模式下,每个块都在自己的jvm中处理。所以如果你改变了状态(例如
stringToSearchFor
)对于在其他主机/jvm/任务上运行的其他每个进程,这都是不可见的。这种不一致性导致在编写map/reduce函数时遵循以下设计原则:
尽可能无国籍。
如果需要state(例如可变类),请不要在map/reduce类中声明引用
static
(否则,测试/开发时的行为将与生产时不同)不可变常量(例如配置键)
String
)应该定义static
以及final
.transient
在hadoop中,hadoop没有序列化usercode(mapper/reducer)类/对象中的任何内容。只有当您对我们不知道的java序列化做了一些事情时,这才是一个问题。对于你的情况,如果
Utility
是一种实用的stringToSearchFor
是一个不可变的常量(因此永远不会更改),您可以安全地声明isThinger
作为static
. 请把它拿走transient
,如果不使用MapReduceBase
.