Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 获取映射线程安全中的更新值_Java_Multithreading_Hashmap - Fatal编程技术网

Java 获取映射线程安全中的更新值

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

我读了第4.3册。在并发实践中委派线程安全使用final和Collections.unmodifiableMap(map)委派线程安全,我尝试创建我的示例,发现返回map时一个线程所做的更改没有得到反映。我做错了什么

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



    }

}