Java 获取映射线程安全中的更新值
我读了第4.3册。在并发实践中委派线程安全使用final和Collections.unmodifiableMap(map)委派线程安全,我尝试创建我的示例,发现返回map时一个线程所做的更改没有得到反映。我做错了什么Java 获取映射线程安全中的更新值,java,multithreading,hashmap,Java,Multithreading,Hashmap,我读了第4.3册。在并发实践中委派线程安全使用final和Collections.unmodifiableMap(map)委派线程安全,我尝试创建我的示例,发现返回map时一个线程所做的更改没有得到反映。我做错了什么 public class MapDem { final Map<Integer, Integer> map; final Map<Integer, Integer> map1; public MapDem() { map = new HashM
public class MapDem {
final Map<Integer, Integer> map;
final Map<Integer, Integer> map1;
public MapDem() {
map = new HashMap<Integer, Integer>();
map.put(1, 10);
map.put(2, 20);
map1 = Collections.unmodifiableMap(map);
}
public Map<Integer, Integer> getMap() {
return Collections.unmodifiableMap(new HashMap<Integer, Integer>(map));
}
public void setValue(int key,int value){
map.replace(key, value);
}
public static void main(String args[]) {
MapDem demo = new MapDem();
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(demo.getMap());
}
});
t3.start();
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
demo.setValue(2, 40);
}
});
t4.start();
try {
t3.join();
t4.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(demo.getMap().size());
}
}
我希望地图始终能看到更新后的值。很抱歉,我在先前的回答中误读了您的代码 要返回“live”视图,您必须与其他线程共享基础映射(毕竟这是“live”的定义。您希望看到其他线程完成的更新)。此共享映射使用的实现(无论是同步还是ConcurrentHashMap)都是无关的。使用
unmodifiable
进行包装与并发无关-它只是将映射设置为“视图”,即只读
所有这些都不会使
t3
在t4
之前执行。为此,你需要引入一种“先发生后发生”的关系。这里最简单的方法是首先在t4
上加入,然后启动t3
我想你不太明白这是怎么回事。也许是我,但我会告诉你我在想什么。这不是等待更新的值,而是只允许对一个对象进行更改,而可以从其他对象进行读取。看看我的代码:
public class DelegatingVehicleTracker {
private final ConcurrentMap<String, String> locations;
private final Map<String, String> unmodifiableMap;
public DelegatingVehicleTracker(Map<String, String> points) {
locations = new ConcurrentHashMap<String, String>(points);
unmodifiableMap = Collections.unmodifiableMap(locations);
}
public Map<String, String> getLocations() {
return unmodifiableMap;
}
public String getLocation(String id) {
return locations.get(id);
}
public void setLocation(String id, int x, int y) {
if (locations.replace(id, x + y + "") == null)
throw new IllegalArgumentException("invalid vehicle name: " + id);
}
public static void main(String[] args) {
HashMap<String, String > vehicles= new HashMap<>();
vehicles.put("1", "1");
DelegatingVehicleTracker tracker = new DelegatingVehicleTracker(vehicles);
Map<String, String> unmodifiableMap = tracker.getLocations();
new Thread(() -> {
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(unmodifiableMap);
}
}).start();
new Thread(() -> {
int i=0;
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
tracker.setLocation("1",i+1, i+2);
i++;
}
}).start();
}
}
public class DelegatingVehicleTracker{
私有最终ConcurrentMap位置;
私有最终地图不可修改地图;
公共授权车辆追踪程序(地图点){
位置=新的ConcurrentHashMap(点);
unmodifiableMap=集合。unmodifiableMap(位置);
}
公共地图getLocations(){
返回不可修改的映射;
}
公共字符串getLocation(字符串id){
返回位置。获取(id);
}
公共void集合位置(字符串id,int x,int y){
if(locations.replace(id,x+y+“”))=null
抛出新的IllegalArgumentException(“无效车辆名称:+id”);
}
公共静态void main(字符串[]args){
HashMap车辆=新的HashMap();
车辆。投入(“1”、“1”);
DelegatingVehicleTracker tracker=新的DelegatingVehicleTracker(车辆);
Map unmodifiableMap=tracker.getLocations();
新线程(()->{
while(true){
试一试{
睡眠(1000);
}捕捉(中断异常e){
e、 printStackTrace();
}
System.out.println(不可修改映射);
}
}).start();
新线程(()->{
int i=0;
while(true){
试一试{
睡眠(1000);
}捕捉(中断异常e){
e、 printStackTrace();
}
设置位置(“1”,i+1,i+2);
i++;
}
}).start();
}
}
在main方法中,我从对象跟踪器获取不可修改的映射,我的一个线程使用它来显示该映射中的值。它将始终显示当前值,因此如果它将在其他线程执行set Location之前执行“sout”,则值将为“old”,但您需要看到这不是“old”值,而是当前值,因为它在执行“sout”时在集合中。正如我在评论中所说的,若你们想看到更新的值,你们需要等待更新,这是另一种情况。这里的线程安全性是,您可以将集合丢弃给所有人,但他们只有阅读此地图的权限,因此您无法直接访问集合。您只能通过DelegatingVehicleTracker执行设置位置。请将您的期望和结果放在这里,以便更好地理解您的问题。更新后的请检查是否符合您的要求?我希望在没有并发映射的情况下实现同样的目标。请查看我在问题中提到的链接,我了解,但在真实场景中我想要一个解决方案,让map总是读取更新的值。如果线程1总是读取map的实际值,您需要考虑这个问题。它不会等待更新的值,除非您将实现某种拦截器,该拦截器将知道旧值,然后在更改后只读。在本例中,线程1是否会在线程2引用我引用此场景的链接之前执行是不确定的
public class DelegatingVehicleTracker {
private final ConcurrentMap<String, String> locations;
private final Map<String, String> unmodifiableMap;
public DelegatingVehicleTracker(Map<String, String> points) {
locations = new ConcurrentHashMap<String, String>(points);
unmodifiableMap = Collections.unmodifiableMap(locations);
}
public Map<String, String> getLocations() {
return unmodifiableMap;
}
public String getLocation(String id) {
return locations.get(id);
}
public void setLocation(String id, int x, int y) {
if (locations.replace(id, x + y + "") == null)
throw new IllegalArgumentException("invalid vehicle name: " + id);
}
public static void main(String[] args) {
HashMap<String, String > vehicles= new HashMap<>();
vehicles.put("1", "1");
DelegatingVehicleTracker tracker = new DelegatingVehicleTracker(vehicles);
Map<String, String> unmodifiableMap = tracker.getLocations();
new Thread(() -> {
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(unmodifiableMap);
}
}).start();
new Thread(() -> {
int i=0;
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
tracker.setLocation("1",i+1, i+2);
i++;
}
}).start();
}
}