Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.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 哈希表、ConcurrentHashMap和数据可见性_Java_Multithreading_Concurrency_Hashmap - Fatal编程技术网

Java 哈希表、ConcurrentHashMap和数据可见性

Java 哈希表、ConcurrentHashMap和数据可见性,java,multithreading,concurrency,hashmap,Java,Multithreading,Concurrency,Hashmap,问题: 我有一个ViewModel基类,它有一个HashMap来存储ViewModel的属性值。然而,我遇到了一个间歇性错误,从这个集合(在一个单独的线程上)读取的数据在添加一个项目后直接返回null private HashMap<String, Serializable> _propertyValues = new HashMap<String, Serializable>(); private HashMap_propertyvalue=new HashMap()

问题: 我有一个ViewModel基类,它有一个HashMap来存储ViewModel的属性值。然而,我遇到了一个间歇性错误,从这个集合(在一个单独的线程上)读取的数据在添加一个项目后直接返回null

private HashMap<String, Serializable> _propertyValues = new HashMap<String, Serializable>();
private HashMap_propertyvalue=new HashMap();
示例:我想在向ViewModel提供用户id时获取用户信息

ViewModel连接到用户ID的PropertyChanged。属性更改处理程序创建后台线程以提取值。后台线程读取用户ID,然后从服务器获取

我们看到的是,在一些罕见的情况下,后台线程直接在提供值(线程1)之后从属性hashmap(线程2)读取null

我的想法:我怀疑这是由于没有线程安全的集合。在回顾线程安全选项时,我遇到了:

  • Hashtable——社区似乎认为它过时了,不鼓励使用它
  • ConcurrentHashMap-由于缺乏可靠的同步,我似乎仍然会遇到问题
  • synchronizedMap(map)-在如何使用它方面似乎很特别,不确定它是否比哈希表有好处
  • 此时,我觉得Hashtable是我想要的,但可以使用确认:

    用例:

  • 每分钟左右,一次阅读100个字母
  • 来自UI线程的频繁写入
  • 定期从需要精确值的后台线程读取。后台线程读取,就在UI线程写入之后
  • 谢谢,
    Trey

    ConcurrentHashMap就可以了。它有内部同步来防止这些问题。它还有其他一些您可能会觉得有用的方法,例如
    putIfAbsent


    它相对于
    集合的主要缺点。synchronizedMap
    的内存占用较大。

    您还可以使用锁,以便在放弃写锁之前其他进程无法访问信息。锁可能是您唯一的选择。在您的案例中,似乎发生了这样的情况:假设值已被写入,但实际上读取线程在写入线程之前被调用,因此值为null。您需要一个锁,以确保在读线程访问该值之前,写线程已经完成。您所说的“特别注意如何使用它”是什么意思?
    synchronizedMap(new HashMap())
    的优点是
    HashMap
    在过去十年中得到了发展,而
    Hashtable
    却没有。您的另一个选择可能是使用
    Executors.newSingleThreadExecutor()
    类似于
    队列
    。这样,一次只执行一个线程,如果读线程在写线程之后提交,则可以保证读线程已经完成。但这可能会导致性能下降。使用它的两种“不正确”方式是直接访问包装映射(明显的违规行为)和在没有同步的情况下对其执行任何类型的迭代(与Hashtable共享的陷阱)。这就是为什么我认为相比之下,
    Hashtable
    没有什么可以提供的。+1
    CHM
    的一个重要且独特的优点是迭代器的一致性。