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”不会阻止检索操作。我不知道出了什么问题
# 1 楼答案
简单的答案是否定的。除非你没有告诉我们其他事情,否则
get
呼叫的阻塞时间不会超过一微秒左右下面是
get
方法及其助手方法的源代码。正如你所见,大部分工作都是在没有任何锁的情况下完成的。条目值的最终获取是在锁下完成的,但锁几乎会立即被释放。。。在finally
块中可以肯定地说
get()
呼叫不是问题的原因资料来源:http://www.java2s.com/Open-Source/Android/android-core/platform-libcore/java/util/concurrent/ConcurrentHashMap.java.htm
(如果链接中断,谷歌“ConcurrentHashMap android source”。)
# 2 楼答案
好吧,它可能会堵塞
(如果我对ConcurrentHashMap的理解有误,请纠正我)
ConcurrentHashMap的整个想法是,用一个大数组存储哈希表,每个人都锁定整个表,它被分割成多个分区(你可以在ConcurrentHashMap的源代码中看到内部类“Segment”)。只有在读取或写入不同分区时,才会出现“无争用”的情况
仔细看另一个答案中引用的源代码Stephen C,你可以在
readValueUnderLock()
中看到lock()
和unlock()
。如果两个线程正在访问同一个分区,它将锁定该段并执行其工作因此,如果您的UI线程
put
指向同一个键(或同一段中的其他键),它将阻塞,直到您完成get()
然而,它并不是你在问题中所说的那种阻碍。它只在访问期间(get/put等)阻塞,一旦操作完成,锁就会被释放