Java有線程安全的set嗎?
點擊關注公眾號,Java干貨及時送達 牛逼!又發(fā)現(xiàn)了一款面試題庫,太全了!!
(點擊查看)
來源:blog.csdn.net/li_canhui/article/details/91393247
在多線程環(huán)境下,要使用線程安全的集合,比如,ConcurrentHashMap是線程安全的HashMap,CopyOnWriteArrayList是線程安全的ArrayList。那么HashSet對應的線程安全集合,是什么呢?java有沒有提供默認實現(xiàn)呢?
在java的concurrent包中,我找到了CopyOnWriteArraySet,那么它是線程安全的嗎?下面是測試代碼。
public?static?void?main(String[]?args)?{
????????Set?set?=?new?CopyOnWriteArraySet<>();
????????ExecutorService?service?=?Executors.newFixedThreadPool(12);
????????int?times?=?10000;
????????AtomicInteger?flag?=?new?AtomicInteger(0);
????????for(int?i?=?0;?i?????????????service.execute(()->{
????????????????set.add("a"?+?flag.getAndAdd(1));
????????????});
????????}
????????service.shutdown();
????????try?{
????????????service.awaitTermination(Long.MAX_VALUE,?TimeUnit.DAYS);
????????}catch?(Exception?e){
????????????e.printStackTrace();
????????}
????????System.out.println(set.size());
????}
經過多次執(zhí)行,結果都是10000。可以說明,CopyOnWriteArraySet是線程安全的Set。
那么CopyOnWriteArraySet是如何保證寫入時的線程安全呢?以下是CopyOnWriteArraySet的add源碼。
????public?boolean?add(E?e)?{
????????return?al.addIfAbsent(e);
????}
????public?boolean?addIfAbsent(E?e)?{
????????Object[]?snapshot?=?getArray();
????????return?indexOf(e,?snapshot,?0,?snapshot.length)?>=?0???false?:
????????????addIfAbsent(e,?snapshot);
????}
????private?static?int?indexOf(Object?o,?Object[]?elements,
???????????????????????????????int?index,?int?fence)?{
????????if?(o?==?null)?{
????????????for?(int?i?=?index;?i?????????????????if?(elements[i]?==?null)
????????????????????return?i;
????????}?else?{
????????????for?(int?i?=?index;?i?????????????????if?(o.equals(elements[i]))
????????????????????return?i;
????????}
????????return?-1;
????}
????private?boolean?addIfAbsent(E?e,?Object[]?snapshot)?{
????????final?ReentrantLock?lock?=?this.lock;
????????lock.lock();
????????try?{
????????????Object[]?current?=?getArray();
????????????int?len?=?current.length;
????????????if?(snapshot?!=?current)?{
????????????????//?Optimize?for?lost?race?to?another?addXXX?operation
????????????????int?common?=?Math.min(snapshot.length,?len);
????????????????for?(int?i?=?0;?i?????????????????????if?(current[i]?!=?snapshot[i]?&&?eq(e,?current[i]))
????????????????????????return?false;
????????????????if?(indexOf(e,?current,?common,?len)?>=?0)
????????????????????????return?false;
????????????}
????????????Object[]?newElements?=?Arrays.copyOf(current,?len?+?1);
????????????newElements[len]?=?e;
????????????setArray(newElements);
????????????return?true;
????????}?finally?{
????????????lock.unlock();
????????}
????}
從源碼可以看出,CopyOnWriteArraySet底層采用了CopyOnWriteArrayList數(shù)據結構來實現(xiàn)。在add元素時,采用的是可重入鎖來實現(xiàn)線程安全。
如有文章對你有幫助,
歡迎關注??、點贊??、轉發(fā)??!
推薦,?Java面試題庫,詳情點擊: 牛逼!又發(fā)現(xiàn)了一款牛逼的Java面試題庫,史上最強! 點擊文末“閱讀原文”可直達
評論
圖片
表情



