0

Maybe this question has the answer but based on my searching words could not find something that fits best for me so posting the question here. This question may seem silly but this is something new to me. Please provide some suggestions or workarounds.

I have a Populator class which has a Map. I want this map to be populated with various values during the code execution then finally I want to obtain all values in Map then process it further based on my requirement.

As of now, I am using the Static method and variable to achieve this. This seems to work fine as of now. But my mentor advised me that this is not going to be thread-safe when processing multiple requests in parallel. I would like to know how to make the below code thread safe.

I would explain with code for better understanding:

Following is my Populcator.class which will be used to populate the Map during the code processing which I access at the end for some further processing. I have created one more class AnotherPopulator as a work-around for the issue but it does not work as per my need:

public class Populator {

    @Getter
    private static final HashMap<String,String> namespaces = new HashMap<>();

    public static void namespacePopulator(String key,String value){
        namespaces.put(key,value);
    }
}

@NoArgsConstructor
@Getter
class AnotherPopulator {

    private final HashMap<String,String> namespaces = new HashMap<>();

    public void namespacePopulator(String key,String value){
        this.namespaces.put(key,value);
    }
}

Following are class A and B which will be invoked my Main.class to populate the Map during the code execution:

public class A {

    public void populatorA() {
        Populator.namespacePopulator("KeyA", "ValueA");
    }

    public void anotherPopulatorA(){
        AnotherPopulator anotherPopulator = new AnotherPopulator();
        anotherPopulator.namespacePopulator("KeyAA","ValueA1");
    }
}

public class B {
    public void populatorB() {
        Populator.namespacePopulator("KeyB", "ValueB");
    }

    public void anotherPopulatorB(){
        AnotherPopulator anotherPopulator = new AnotherPopulator();
        anotherPopulator.namespacePopulator("KeyB1","ValueB1");
    }
}

Following is my Main.class which will invoke A and B then finally obtain the Map with all the values populated during the execution:

public class Main {
    public static void main(String[] args) {
        A a = new A();
        B b = new B();

        a.populatorA();
        b.populatorB();

        //This will provide me with desired result but does not provide the thread safety
        System.out.println(Populator.getNamespaces());

        System.out.println("****************************");

        //This will provide thread safety but does not provide the desired result I would want as new object will be created at every stage
        AnotherPopulator anotherPopulator = new AnotherPopulator();
        System.out.println(anotherPopulator.getNamespaces());

        //I would like to populate a Map present in class from various classes during the execution then finally I would like to obtain all the values that were added during the
        // execution but want to do this using the thread safety approach
        
    }
}

Following is the output I get. 1st part has the values I need but it's not a thread-safe approach. 2nd part does not have the values I need but it's a thread-safe approach I believe.

{KeyB=ValueB, KeyA=ValueA}
****************************
{}

I would like to know how can I declare a Map using the Thread-safety approach and populate it during the entire code execution life cycle and then finally obtain all the values together.

I hope I am able to explain the issue clearly. Any help/workarounds/suggestions will be really helpful for me. Thanks in advance.

BATMAN_2008
  • 2,788
  • 3
  • 31
  • 98

1 Answers1

0

As mentioned in the comment use ConcurrentHashMap

public class Populator {

    @Getter
    private static final ConcurrentHashMap<String,String> namespaces = new ConcurrentHashMap <>();

    public static void namespacePopulator(String key,String value){
        namespaces.putIfAbsent(key,value);
    }
}
Michael Katt
  • 615
  • 1
  • 5
  • 18