概述copyonwritearraylist是jdk concurrent包中提供的乙個非阻塞型的,執行緒安全的list實現。
copyonwritearraylist在進行資料修改時,都不會對資料進行鎖定,每次修改時,先拷貝整個陣列,然後修改其中的一些元素,完成上述操作後,替換整個陣列的指標。
對copyonwritearraylist進行讀取時,也不進行資料鎖定,直接返回需要查詢的資料,如果需要返回整個陣列,那麼會將整個陣列拷貝乙份,再返回,保證內部array在任何情況下都是唯讀的。
應用場景
正因為上述讀寫特性,如果需要頻繁對copyonwritearraylist進行修改,而很少讀取的話,那麼會嚴重降低系統效能。
因為沒有鎖的干預,所以copyonwritearraylist在少量修改,頻繁讀取的場景下,有很好的併發效能。
資料結構
copyonwritearraylist中,包含乙個array陣列物件,這個物件,只能由getarray()和setarray()兩個方法訪問,原始碼如下:
private
volatile
transient
object
array
;final
object
getarray
()final
void
setarray
(object
a)
併發安全保證
copyonwritearraylist在併發情況下,可以提供高效能的併發讀取,並且保證讀取的內容一定是正確的,不受多執行緒併發問題影響的。在本文中,我們從建構函式的併發安全性、訪問單個元素的併發安全性、訪問整個陣列的併發安全性和寫操作的併發安全性,四個方面進行分析。
建構函式的併發安全性
copyonwritearraylist提供了三個建構函式,分別為
上述三個方法的原始碼如下:
public
copyonwritearraylist
()/**
* 根據傳入引數c的長度,構造乙個同樣長度的object物件,並且將c的內容,依次填入此object物件中
* 注意:
* 1. 這裡對於c中內容的複製,是淺拷貝而非深拷貝
* 2. 這裡的建構函式,未顯式判斷c是否為null,實際上如果c為null,會丟擲空指標異常
*/public
copyonwritearraylist
(collection
<?
extends
e>c)
/*** 根據傳入引數的長度,構造出乙個同樣長度,內容一致的陣列物件,封裝在copyonwritearraylist中
* 注意:
* 1. 這裡對於陣列內容的複製,是淺拷貝而非深拷貝
* 2.
這裡的建構函式,未顯式判斷傳入引數是否為null,實際上如果傳入引數為null,會丟擲空指標異常
*/public
copyonwritearraylist(e
tocopyin
)
訪問單個元素的併發安全性
訪問單個元素時,不會對原有陣列造成任何影響,所以肯定是執行緒安全的。這裡列舉一兩個方法的實現原始碼,其他的不再贅述:
public
e get
(int
index
)public
intindexof
(objecto)
private
static
intindexof
(objecto,
object
elements
,int
index
,int
fence
)else
return-1
;}
訪問整個陣列的併發安全性
訪問整個陣列的操作,包括clone以及toarray方法,這些方法在執行時,不會直接返回內部封裝的array物件引用,而是將其拷貝乙份,再返回。注意,這裡的拷貝,也是淺拷貝。
原始碼如下:
www.520xunlong.com
public
object
toarray
()public
<
t>t
toarray
(t a)}
public
object
clone
()catch
(clonenotsupportedexceptione)
}
寫操作的併發安全性
寫操作的併發安全性,是copyonwritearraylist中最重要的一點,只***寫操作是安全的,才能保證併發是安全的。
set方法,是寫操作的乙個基本方法,其原始碼如下:
public
e set
(int
index
,e element
)else
return(e
)oldvalue;}
finally
}
為list末尾新增乙個新元素,使用add方法,其原始碼如下:
同時,也可以將某個元素加入到某個特定的位置,如下所示:public
boolean
add(
e e)
finally
}
public
void
add(
intindex
,e element
)else
newelements
[index]=
element
;setarray
(newelements);}
finally
}
copyonwritearraylist同時也提供了從list中,移除某個元素的方法,原始碼如下:
也可以直接移除list中的某個物件,原始碼如下:public
e remove
(int
index
)else
return(e
)oldvalue;}
finally
}
其他修改的方法,原理上都是類似的,這裡不再贅述。sspublic
boolean
remove
(objecto)
setarray
(newelements
);return
true
;/* 找到了需要刪除的元素,並正常刪除,返回true */
}else
}/* 當需要移除的元素,在陣列最後,直接將新的陣列賦值過去 */if(
eq(o,
elements
[newlen
]))}
/* 未找到需要刪除的元素,返回false */
return
false;}
finally
}
azkaban web server原始碼解析
azkaban主要用於hadoop相關job任務的排程,但也可以應用任何需要排程管理的任務,可以完全代替crontab。azkaban主要分為web server 任務上傳,管理,排程 executor server 接受web server的排程指令,進行任務執行 1.資料表 projects 工...
JDK LinkedHashMap原始碼解析
今天來分析一下jdk linkedhashmap的源 public class linkedhashmapextends hashmapimplements map可以看到,linkedhashmap繼承自hashmap,並且也實現了map介面,所以linkedhashmap沿用了hashmap的大...
Redux原始碼createStore解讀常用方法
const store createstore reducer,preloadedstate enhancer 直接返回當前currentstate,獲取state值,return state 我覺得應該深轉殖乙個新的物件返回,不然有可能會被外部修改 function getstate consol...