有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java是否获得块ConcurrentHashMap?

片段1:

private void startLoadingName() {
    for (ConcurrentHashMap.Entry<TextView, Long> entry : mPendingNameRequest.entrySet()) {
        long callId = (Long)entry.getValue();
        NameHolder nameHolder = mNameCache.get(callId);
        nameHolder.name = QueryUtils.loadNameFromDb(mContext, callId);
        nameHolder.status = NameHolder.LOADED;
        // mNameCache is a ConcurrentHashMap
        mNameCache.put(callId, nameHolder);

        updateContactCachedName(callId, nameHolder);
    }

    GsItemLoader.this.sendEmptyMessage(MESSAGE_SET_NAME);
}

此代码段在UI线程以外的线程上运行。每次执行时,ListView滚动总是变慢,因此代码段中一定有什么东西阻塞了UI线程

我发现NameHolder nameHolder = mNameCache.get(callId);将阻止mNameCache直到mNameCache.put(callId, nameHolder);。但文件称“ConcurrentHashMap”不会阻止检索操作。我不知道出了什么问题


共 (2) 个答案

  1. # 1 楼答案

    简单的答案是否定的。除非你没有告诉我们其他事情,否则get呼叫的阻塞时间不会超过一微秒左右

    下面是get方法及其助手方法的源代码。正如你所见,大部分工作都是在没有任何锁的情况下完成的。条目值的最终获取是在锁下完成的,但锁几乎会立即被释放。。。在finally块中

    可以肯定地说get()呼叫不是问题的原因


        /**
         * Reads value field of an entry under lock. Called if value
         * field ever appears to be null. This is possible only if a
         * compiler happens to reorder a HashEntry initialization with
         * its table assignment, which is legal under memory model
         * but is not known to ever occur.
         */
        V readValueUnderLock(HashEntry<K,V> e) {
            lock();
            try {
                return e.value;
            } finally {
                unlock();
            }
        }
    
        /* Specialized implementations of map methods */
    
        V get(Object key, int hash) {
            if (count != 0) { // read-volatile
                HashEntry<K,V> e = getFirst(hash);
                while (e != null) {
                    if (e.hash == hash && key.equals(e.key)) {
                        V v = e.value;
                        if (v != null)
                            return v;
                        return readValueUnderLock(e); // recheck
                    }
                    e = e.next;
                }
            }
            return null;
        }
    

    资料来源:http://www.java2s.com/Open-Source/Android/android-core/platform-libcore/java/util/concurrent/ConcurrentHashMap.java.htm

    (如果链接中断,谷歌“ConcurrentHashMap android source”。)

  2. # 2 楼答案

    好吧,它可能会堵塞

    (如果我对ConcurrentHashMap的理解有误,请纠正我)

    ConcurrentHashMap的整个想法是,用一个大数组存储哈希表,每个人都锁定整个表,它被分割成多个分区(你可以在ConcurrentHashMap的源代码中看到内部类“Segment”)。只有在读取或写入不同分区时,才会出现“无争用”的情况

    仔细看另一个答案中引用的源代码Stephen C,你可以在readValueUnderLock()中看到lock()unlock()。如果两个线程正在访问同一个分区,它将锁定该段并执行其工作

    因此,如果您的UI线程put指向同一个键(或同一段中的其他键),它将阻塞,直到您完成get()

    然而,它并不是你在问题中所说的那种阻碍。它只在访问期间(get/put等)阻塞,一旦操作完成,锁就会被释放