MSR MSR - 6 months ago 20
Java Question

Clear a Map in nested loop in multithreaded environement

i am working in a multithreaded environment where i have a synchronized multimap. I am using that map in nested loops and i want to clear the value for each transaction in that nested loop. how can achieve this:

public class Test1 {
public static void main(String[] args){
ExecutorService executor = Executors.newFixedThreadPool(10);
final Multimap<Object, Object> map =
Multimaps.synchronizedMultimap(ArrayListMultimap.create());

final List<String> listA = new ArrayList<String>();
listA.add("e");
listA.add("f");
listA.add("g");
final List<String> listB = new ArrayList<String>();
listB.add("e");
listB.add("f");
listB.add("g");
final List<String> listC = new ArrayList<String>();
listC.add("e");
listC.add("f");
listC.add("g");


for (final String stateId : listA) {
for (final String gradeList : listB) {
for (final String subjectList : listC) {
executor.execute(new Runnable() {
@Override
public void run() {
map.clear();
map.put("f", "hi");
System.out.println("map before "+map);

System.out.println("map after "+map);
}
});
}

}
}
executor.shutdown();
try {
executor.awaitTermination(24L, TimeUnit.HOURS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


But this is not resulting in correct output. Sometimes i can see the multiple values and sometimes i see no values while printing the map. Can anyone suggest the changes for this please?

Answer Source

You are running all operations at the same time in the executor (well, 10 at a time). These calls here:

        map.clear();
        map.put("f", "hi");
        System.out.println("map before "+map);
        System.out.println("map after "+map);

are not part of a synchronized block, and instructions from multiple threads may be interleaved across them, f.e. the following is a valid interleaving across threads T1 and T2:

 T1:       map.clear();
 T2:       map.clear();
 T1:       map.put("f", "hi");
 T2:       map.put("f", "hi");
 T2:       System.out.println("map before "+map);
 T1:       System.out.println("map before "+map);
 T1:       System.out.println("map after "+map);
 T2:       System.out.println("map after "+map);

I'll leave how to synchronize across multiple instructions as an exercise for the reader.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download