溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java concurrency集合之ConcurrentSkipListSet_動力節(jié)點Java學(xué)院整理

發(fā)布時間:2020-10-24 12:37:40 來源:腳本之家 閱讀:235 作者:skywang12345 欄目:編程語言

ConcurrentSkipListSet介紹

ConcurrentSkipListSet是線程安全的有序的集合,適用于高并發(fā)的場景。
ConcurrentSkipListSet和TreeSet,它們雖然都是有序的集合。但是,第一,它們的線程安全機制不同,TreeSet是非線程安全的,而ConcurrentSkipListSet是線程安全的。第二,ConcurrentSkipListSet是通過ConcurrentSkipListMap實現(xiàn)的,而TreeSet是通過TreeMap實現(xiàn)的。

 ConcurrentSkipListSet原理和數(shù)據(jù)結(jié)構(gòu)

ConcurrentSkipListSet的數(shù)據(jù)結(jié)構(gòu),如下圖所示:

Java concurrency集合之ConcurrentSkipListSet_動力節(jié)點Java學(xué)院整理

說明:

(01) ConcurrentSkipListSet繼承于AbstractSet。因此,它本質(zhì)上是一個集合。
(02) ConcurrentSkipListSet實現(xiàn)了NavigableSet接口。因此,ConcurrentSkipListSet是一個有序的集合。
(03) ConcurrentSkipListSet是通過ConcurrentSkipListMap實現(xiàn)的。它包含一個ConcurrentNavigableMap對象m,而m對象實際上是ConcurrentNavigableMap的實現(xiàn)類ConcurrentSkipListMap的實例。ConcurrentSkipListMap中的元素是key-value鍵值對;而ConcurrentSkipListSet是集合,它只用到了ConcurrentSkipListMap中的key! 

ConcurrentSkipListSet函數(shù)列表

// 構(gòu)造一個新的空 set,該 set 按照元素的自然順序?qū)ζ溥M(jìn)行排序。
ConcurrentSkipListSet()
// 構(gòu)造一個包含指定 collection 中元素的新 set,這個新 set 按照元素的自然順序?qū)ζ溥M(jìn)行排序。
ConcurrentSkipListSet(Collection<? extends E> c)
// 構(gòu)造一個新的空 set,該 set 按照指定的比較器對其元素進(jìn)行排序。
ConcurrentSkipListSet(Comparator<? super E> comparator)
// 構(gòu)造一個新 set,該 set 所包含的元素與指定的有序 set 包含的元素相同,使用的順序也相同。
ConcurrentSkipListSet(SortedSet<E> s)

// 如果此 set 中不包含指定元素,則添加指定元素。
boolean add(E e)
// 返回此 set 中大于等于給定元素的最小元素;如果不存在這樣的元素,則返回 null。
E ceiling(E e)
// 從此 set 中移除所有元素。
void clear()
// 返回此 ConcurrentSkipListSet 實例的淺表副本。
ConcurrentSkipListSet<E> clone()
// 返回對此 set 中的元素進(jìn)行排序的比較器;如果此 set 使用其元素的自然順序,則返回 null。
Comparator<? super E> comparator()
// 如果此 set 包含指定的元素,則返回 true。
boolean contains(Object o)
// 返回在此 set 的元素上以降序進(jìn)行迭代的迭代器。
Iterator<E> descendingIterator()
// 返回此 set 中所包含元素的逆序視圖。
NavigableSet<E> descendingSet()
// 比較指定對象與此 set 的相等性。
boolean equals(Object o)
// 返回此 set 中當(dāng)前第一個(最低)元素。
E first()
// 返回此 set 中小于等于給定元素的最大元素;如果不存在這樣的元素,則返回 null。
E floor(E e)
// 返回此 set 的部分視圖,其元素嚴(yán)格小于 toElement。
NavigableSet<E> headSet(E toElement)
// 返回此 set 的部分視圖,其元素小于(或等于,如果 inclusive 為 true)toElement。
NavigableSet<E> headSet(E toElement, boolean inclusive)
// 返回此 set 中嚴(yán)格大于給定元素的最小元素;如果不存在這樣的元素,則返回 null。
E higher(E e)
// 如果此 set 不包含任何元素,則返回 true。
boolean isEmpty()
// 返回在此 set 的元素上以升序進(jìn)行迭代的迭代器。
Iterator<E> iterator()
// 返回此 set 中當(dāng)前最后一個(最高)元素。
E last()
// 返回此 set 中嚴(yán)格小于給定元素的最大元素;如果不存在這樣的元素,則返回 null。
E lower(E e)
// 獲取并移除第一個(最低)元素;如果此 set 為空,則返回 null。
E pollFirst()
// 獲取并移除最后一個(最高)元素;如果此 set 為空,則返回 null。
E pollLast()
// 如果此 set 中存在指定的元素,則將其移除。
boolean remove(Object o)
// 從此 set 中移除包含在指定 collection 中的所有元素。
boolean removeAll(Collection<?> c)
// 返回此 set 中的元素數(shù)目。
int size()
// 返回此 set 的部分視圖,其元素范圍從 fromElement 到 toElement。
NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive)
// 返回此 set 的部分視圖,其元素從 fromElement(包括)到 toElement(不包括)。
NavigableSet<E> subSet(E fromElement, E toElement)
// 返回此 set 的部分視圖,其元素大于等于 fromElement。
NavigableSet<E> tailSet(E fromElement)
// 返回此 set 的部分視圖,其元素大于(或等于,如果 inclusive 為 true)fromElement。
NavigableSet<E> tailSet(E fromElement, boolean inclusive)

ConcurrentSkipListSet是通過ConcurrentSkipListMap實現(xiàn)的,它的接口基本上都是通過調(diào)用ConcurrentSkipListMap接口來實現(xiàn)的。這里就不再對它的源碼進(jìn)行分析了。 

ConcurrentSkipListSet示例

import java.util.*;
import java.util.concurrent.*;

/*
 *  ConcurrentSkipListSet是“線程安全”的集合,而TreeSet是非線程安全的。
 *
 *  下面是“多個線程同時操作并且遍歷集合set”的示例
 *  (01) 當(dāng)set是ConcurrentSkipListSet對象時,程序能正常運行。
 *  (02) 當(dāng)set是TreeSet對象時,程序會產(chǎn)生ConcurrentModificationException異常。
 *
 * @author skywang
 */
public class ConcurrentSkipListSetDemo1 {

  // TODO: set是TreeSet對象時,程序會出錯。
  //private static Set<String> set = new TreeSet<String>();
  private static Set<String> set = new ConcurrentSkipListSet<String>();
  public static void main(String[] args) {
  
    // 同時啟動兩個線程對set進(jìn)行操作!
    new MyThread("a").start();
    new MyThread("b").start();
  }

  private static void printAll() {
    String value = null;
    Iterator iter = set.iterator();
    while(iter.hasNext()) {
      value = (String)iter.next();
      System.out.print(value+", ");
    }
    System.out.println();
  }

  private static class MyThread extends Thread {
    MyThread(String name) {
      super(name);
    }
    @Override
    public void run() {
        int i = 0;
      while (i++ < 10) {
        // “線程名” + "序號"
        String val = Thread.currentThread().getName() + (i%6);
        set.add(val);
        // 通過“Iterator”遍歷set。
        printAll();
      }
    }
  }
}

(某一次)運行結(jié)果:

a1, b1, 
a1, a1, a2, b1, 
b1, a1, a2, a3, b1,

a1, a2, a3, a1, a4, b1, b2, 
a2, a1, a2, a3, a4, a5, b1, b2, 
a3, a0, a4, a5, a1, b1, a2, b2, 
a3, a0, a4, a1, a5, a2, b1, a3, b2, a4, b3, 
a5, a0, b1, a1, b2, a2, b3, 
a3, a0, a4, a1, a5, a2, b1, a3, b2, a4, b3, a5, b4, 
b1, a0, b2, a1, b3, a2, b4, 
a3, a0, a4, a1, a5, a2, b1, a3, b2, a4, b3, a5, b4, b1, b5, 
b2, a0, a1, a2, a3, a4, a5, b3, b1, b4, b2, b5, 
b3, a0, b4, a1, b5, 
a2, a0, a3, a1, a4, a2, a5, a3, b0, a4, b1, a5, b2, b0, b3, b1, b4, b2, b5, b3, 
b4, a0, b5, 
a1, a2, a3, a4, a5, b0, b1, b2, b3, b4, b5, 
a0, a1, a2, a3, a4, a5, b0, b1, b2, b3, b4, b5, 
a0, a1, a2, a3, a4, a5, b0, b1, b2, b3, b4, b5, 
a0, a1, a2, a3, a4, a5, b0, b1, b2, b3, b4, b5, 

結(jié)果說明:

示例程序中,啟動兩個線程(線程a和線程b)分別對ConcurrentSkipListSet進(jìn)行操作。以線程a而言,它會先獲取“線程名”+“序號”,然后將該字符串添加到ConcurrentSkipListSet集合中;接著,遍歷并輸出集合中的全部元素。 線程b的操作和線程a一樣,只不過線程b的名字和線程a的名字不同。

當(dāng)set是ConcurrentSkipListSet對象時,程序能正常運行。如果將set改為TreeSet時,程序會產(chǎn)生ConcurrentModificationException異常。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI