2012-04-16 90 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