2017-08-16 46 views
0

我正在多線程環境中工作,我有一個同步多地圖。我在嵌套循環中使用該映射,我想清除該嵌套循環中每個事務的值。如何實現這一點:在多線程環境中清除嵌套循環中的地圖

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(); 
} 
} 

但是,這不會導致正確的輸出。有時我可以看到多個值,有時我在打印地圖時看不到任何值。任何人都可以提出這個更改嗎?

回答

1

您正在執行器中同時運行所有操作(呃,一次10個)。這裏這些調用:

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

是一個synchronized塊部分,從多個線程的指令可以在它們之間交錯,F.E.以下是線程T1和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); 

我將離開如何在多條指令中同步作爲練習讀者。

+0

明白了!非常感謝您的明確解釋。我利用地圖的同步塊,像魅力一樣工作。非常感謝您的完美解釋。 :) @TassosBassoukos – MSR

+0

這就是我正在尋找的解決方案。但同步在這裏引起嚴重的性能問題。它需要永久完成。它需要進行大約5000次API調用,並且需要永久完成。請問有什麼解決辦法嗎? – MSR

+0

請勿使用共享狀態,請勿在持有鎖定時使用網絡呼叫。或者,使用像rxjava +翻新之類的東西。 –