2012-04-16 79 views
5

我想知道是否可以添加一个可以在多个map()调用中使用的成员对象。例如,一个StringBuilder:Hadoop的Mapper对象是否跨多个线程共享?

private StringBuilder builder; 

public void map(...){ 
    ... 

    builder.setLength(0); 
    builder.append(a); 
    builder.append(b); 
    builder.append(c); 
    d = builder.toString(); 

    ... 
} 

显然,如果映射器对象在多个线程共享,构建器对象上方不会像预期的那样,由于从一个以上的线程的并发访问。

所以我的问题是:是否确定hadoop中的每个线程都会为自己使用一个专用的映射器对象?或者它是一种可配置的行为?

感谢

回答

2

只要你不使用MultithreadedMapper类,但你自己的,就不会有问题。 map()被称为顺序,而不是并行。

通常使用StringBuilder或其他数据结构来缓冲调用之间的一些对象。 但请确保从输入对象中克隆对象,只有一个对象,并且它会一遍又一遍地填充以防止大量的GC。

所以没有必要同步或照顾竞争条件。

+0

这就是我想知道的。谢谢。 – JRaSH 2012-04-16 11:30:22

+1

如果您需要整个Key/Value对象,则只需克隆对象;否则,如果您只需要添加到StringBuffer的某些内容,则无问题。不要忘记添加清理方法(我忘记了要覆盖的名称),以便在Map调用之间缓冲或写入Reducer,否则最终会有一些数据永远不会发送到Reducers。 – Drizzt321 2012-04-16 23:22:45

0

我不认为这是可能的。原因是每个映射器都运行在它自己的JVM中(它们将分布在不同的机器上),因此您无法轻松地跨多个映射器或简化器共享变量或对象。

现在,如果所有的映射器在同一节点上运行,我相信这是对JVM的配置重用的地方,但老实说,我不会打扰,特别是如果你需要的是一个StringBuilder :)

我以前曾经见过这个问题,并且可以通过更改应用程序的设计很容易地解决它。也许你可以告诉更多关于你想要完成的事情,看看这是否真的需要。如果你确实需要它,你仍然可以序列化你的对象,把它放在HDFS中,然后用每个映射器读取它,反序列化它,但是看起来倒退了。

+0

嗨,我不是要在多个映射器上共享一个变量。据我所知,每个mapper的map()方法被称为多次,这就是我认为我可以节省一些资源的地方。因此,通过将一个成员对象放入映射器实例中,可以在多次调用map()的情况下重新调用该对象,而无需重复执行init和de-init。我的担心是:如果同时调用map(),则可能会导致使用memeber对象的问题。 – JRaSH 2012-04-16 03:22:05