Java 中地图列表的并发访问
Concurrent access of List of Map in Java
我有以下列表。
List<Map<String,String>> input = new ArrayList<Map<String,String>>();
我有一个要求,在线程中访问 List 中的每个 Map 对象。
保证没有两个线程访问同一个地图对象。
for(Map<String,String> input : inputList){
triggerThread(input); // Thread modifies the input. It adds elements in the input map
}
我是否需要使用 synchronizedList(inputList) 或 synchronizedmap(input) 或直接使用 input map 而不使用任何同步逻辑是否可以?哪个设计好?
这可能是基本问题。我对如何实施感到很困惑。
class Main{
public static void main(String[] args){
List<Map<String,String>> inputList = new ArrayList<Map<String,String>>();
Map<String,String> input = new HashMap<String,String>();
input.put("attr1","param1");
inputList.add(input);
ExecutorService pool= Executors.newFixedThreadPool(10);
for(Map<String,String> input : inputList){
RequestHandler request = new RequestHandler(input);
pool.submit(request);
}
}
}
class RequestHandler extends Runnable{
Map<String,String> input;
RequestHandler(Map<String,String> input){
this.input=input;
}
@Override
public void run() {
//writing logic vaguely
input.add("attr2", "param2");
}
}
假设如下:
inputList
列表由一个线程填充,然后未被其他线程修改(即没有元素 added/removed)
- 没有两个线程访问
input
映射中的同一个映射对象(如问题所述)
如果是这种情况,则无需在 inputList
或 input
上进行同步。
另一方面,如果您将通过其他线程访问 inputList
本身,请使用 Collections.syncrhonizedList() 例如。
由于列表永远不会更改并且实际上是不可变的,因此您唯一关心的是 Map 元素。一个线程对 Map 元素所做的更改可能对另一个线程不可见。要解决这个问题,您可以使用 ConcurrentHashMap:
例如:
List<Map<String,String>> input = new ArrayList<>();
input.add(new ConcurrentHashMap<>());
...
作为参考,请查看 this 尤其是关于可见性的部分
我有以下列表。
List<Map<String,String>> input = new ArrayList<Map<String,String>>();
我有一个要求,在线程中访问 List 中的每个 Map 对象。 保证没有两个线程访问同一个地图对象。
for(Map<String,String> input : inputList){
triggerThread(input); // Thread modifies the input. It adds elements in the input map
}
我是否需要使用 synchronizedList(inputList) 或 synchronizedmap(input) 或直接使用 input map 而不使用任何同步逻辑是否可以?哪个设计好?
这可能是基本问题。我对如何实施感到很困惑。
class Main{
public static void main(String[] args){
List<Map<String,String>> inputList = new ArrayList<Map<String,String>>();
Map<String,String> input = new HashMap<String,String>();
input.put("attr1","param1");
inputList.add(input);
ExecutorService pool= Executors.newFixedThreadPool(10);
for(Map<String,String> input : inputList){
RequestHandler request = new RequestHandler(input);
pool.submit(request);
}
}
}
class RequestHandler extends Runnable{
Map<String,String> input;
RequestHandler(Map<String,String> input){
this.input=input;
}
@Override
public void run() {
//writing logic vaguely
input.add("attr2", "param2");
}
}
假设如下:
inputList
列表由一个线程填充,然后未被其他线程修改(即没有元素 added/removed)- 没有两个线程访问
input
映射中的同一个映射对象(如问题所述)
如果是这种情况,则无需在 inputList
或 input
上进行同步。
另一方面,如果您将通过其他线程访问 inputList
本身,请使用 Collections.syncrhonizedList() 例如。
由于列表永远不会更改并且实际上是不可变的,因此您唯一关心的是 Map 元素。一个线程对 Map 元素所做的更改可能对另一个线程不可见。要解决这个问题,您可以使用 ConcurrentHashMap:
例如:
List<Map<String,String>> input = new ArrayList<>();
input.add(new ConcurrentHashMap<>());
...
作为参考,请查看 this 尤其是关于可见性的部分