Java 是否获取块ConcurrentHashMap?
片段1:Java 是否获取块ConcurrentHashMap?,java,android,Java,Android,片段1: private void startLoadingName() { for (ConcurrentHashMap.Entry<TextView, Long> entry : mPendingNameRequest.entrySet()) { long callId = (Long)entry.getValue(); NameHolder nameHolder = mNameCache.get(callId); name
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);
}
private void startingname(){
for(ConcurrentHashMap.Entry:mPendingNameRequest.entrySet()){
long callId=(long)entry.getValue();
NameHolder-NameHolder=mNameCache.get(callId);
nameHolder.name=QueryUtils.loadNameFromDb(mContext,callId);
nameHolder.status=nameHolder.LOADED;
//mNameCache是一个ConcurrentHashMap
mNameCache.put(callId,name holder);
updateContactCachedName(callId,姓名持有者);
}
GsItemLoader.this.sendEmptyMessage(MESSAGE\u SET\u NAME);
}
此代码段在UI线程以外的线程上运行。每次执行时,ListView滚动总是变慢,因此代码段中一定有什么东西阻塞了UI线程
我发现
NameHolder-NameHolder=mNameCache.get(callId)
将阻止mNameCache
直到mNameCache.put(callId,nameHolder)代码>。但文件称“ConcurrentHashMap”不会阻止检索操作。我不知道出了什么问题。简单的答案是否定的。除非您没有告诉我们其他事情,否则get
呼叫的阻塞时间不会超过一微秒左右
下面是get
方法及其助手方法的源代码。正如您所看到的,大部分工作都是在没有任何锁的情况下完成的。条目值的最终获取是在锁下完成的,但锁几乎会立即释放。。。在最后
块中
可以肯定地说,get()
调用不是问题的原因
/**
*读取锁定项的值字段。调用if值
*字段始终显示为空。这只有在
*编译器碰巧对HashEntry初始化进行了重新排序
*它的表分配,在内存模式下是合法的
*但目前还不知道会发生什么。
*/
V readValueUnderLock(散列项e){
锁();
试一试{
返回e.value;
}最后{
解锁();
}
}
/*map方法的专门实现*/
V get(对象键,int散列){
如果(计数!=0){//read volatile
HashEntry e=getFirst(哈希);
while(e!=null){
如果(e.hash==hash&&key.equals(e.key)){
V=e值;
如果(v!=null)
返回v;
返回readValueUnderLock(e);//重新检查
}
e=e.next;
}
}
返回null;
}
资料来源:
(如果链接中断,谷歌“ConcurrentHashMapandroid source”。简单的答案是否定的。除非您没有告诉我们其他事情,否则get
呼叫将不会阻塞超过一微秒左右的时间
下面是get
方法及其助手方法的源代码。正如您所看到的,大部分工作都是在没有任何锁的情况下完成的。条目值的最终获取是在锁下完成的,但锁几乎会立即释放。。。在最后
块中
可以肯定地说,get()
调用不是问题的原因
/**
*读取锁定项的值字段。调用if值
*字段始终显示为空。这只有在
*编译器碰巧对HashEntry初始化进行了重新排序
*它的表分配,在内存模式下是合法的
*但目前还不知道会发生什么。
*/
V readValueUnderLock(散列项e){
锁();
试一试{
返回e.value;
}最后{
解锁();
}
}
/*map方法的专门实现*/
V get(对象键,int散列){
如果(计数!=0){//read volatile
HashEntry e=getFirst(哈希);
while(e!=null){
如果(e.hash==hash&&key.equals(e.key)){
V=e值;
如果(v!=null)
返回v;
返回readValueUnderLock(e);//重新检查
}
e=e.next;
}
}
返回null;
}
资料来源:
(如果链接中断,谷歌“ConcurrentHashMapandroid source”。AFAIK,它可能会被阻止
(如果我对ConcurrentHashMap的理解有误,请纠正我)
ConcurrentHashMap的整体思想是,使用一个大数组存储哈希表,每个人都锁定整个表,它被分割成多个分区(您可以在ConcurrentHashMap的源代码中看到内部类“Segment”)。只有在读取或写入不同分区时,才会出现“无争用”的情况
仔细查看另一个答案中引用的源代码Stephen C,您可以在readValueUnderLock()
中看到lock()
和unlock()
。如果两个线程正在访问同一个分区,它将锁定该段并执行其工作
因此,如果您的UI线程是put
ting到同一个键(或同一段中的其他键),它将阻塞,直到您完成get()
然而,这并不是你在问题中所说的阻碍。它仅在访问期间(获取/放置等)阻塞,并且一旦操作完成,锁即被释放。好的,它可能会阻塞
(如果我对ConcurrentHashMap的理解有误,请纠正我)
ConcurrentHashMap的整体思想是,使用一个大数组存储哈希表,每个人都锁定整个表,它被分割成多个分区(您可以在ConcurrentHashMap的源代码中看到内部类“Segment”)。只有在读取或写入不同分区时,才会出现“无争用”的情况
请仔细查看在中引用的源代码Stephen C
/**
* 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;
}