Java多线程系列--“JUC集合”06之 ConcurrentSkipListSet
来源:互联网 发布:晋城网络台少年心学院 编辑:程序博客网 时间:2024/06/18 12:07
概要
本章对Java.util.concurrent包中的ConcurrentSkipListSet类进行详细的介绍。内容包括:
ConcurrentSkipListSet介绍
ConcurrentSkipListSet原理和数据结构
ConcurrentSkipListSet函数列表
ConcurrentSkipListSet源码(JDK1.7.0_40版本)
ConcurrentSkipListSet示例
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3498634.html
ConcurrentSkipListSet介绍
ConcurrentSkipListSet是线程安全的有序的集合,适用于高并发的场景。
ConcurrentSkipListSet和TreeSet,它们虽然都是有序的集合。但是,第一,它们的线程安全机制不同,TreeSet是非线程安全的,而ConcurrentSkipListSet是线程安全的。第二,ConcurrentSkipListSet是通过ConcurrentSkipListMap实现的,而TreeSet是通过TreeMap实现的。
ConcurrentSkipListSet原理和数据结构
ConcurrentSkipListSet的数据结构,如下图所示:
说明:
(01) ConcurrentSkipListSet继承于AbstractSet。因此,它本质上是一个集合。
(02) ConcurrentSkipListSet实现了NavigableSet接口。因此,ConcurrentSkipListSet是一个有序的集合。
(03) ConcurrentSkipListSet是通过ConcurrentSkipListMap实现的。它包含一个ConcurrentNavigableMap对象m,而m对象实际上是ConcurrentNavigableMap的实现类ConcurrentSkipListMap的实例。ConcurrentSkipListMap中的元素是key-value键值对;而ConcurrentSkipListSet是集合,它只用到了ConcurrentSkipListMap中的key!
ConcurrentSkipListSet函数列表
// 构造一个新的空 set,该 set 按照元素的自然顺序对其进行排序。ConcurrentSkipListSet()// 构造一个包含指定 collection 中元素的新 set,这个新 set 按照元素的自然顺序对其进行排序。ConcurrentSkipListSet(Collection<? extends E> c)// 构造一个新的空 set,该 set 按照指定的比较器对其元素进行排序。ConcurrentSkipListSet(Comparator<? super E> comparator)// 构造一个新 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 中的元素进行排序的比较器;如果此 set 使用其元素的自然顺序,则返回 null。Comparator<? super E> comparator()// 如果此 set 包含指定的元素,则返回 true。boolean contains(Object o)// 返回在此 set 的元素上以降序进行迭代的迭代器。Iterator<E> descendingIterator()// 返回此 set 中所包含元素的逆序视图。NavigableSet<E> descendingSet()// 比较指定对象与此 set 的相等性。boolean equals(Object o)// 返回此 set 中当前第一个(最低)元素。E first()// 返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素,则返回 null。E floor(E e)// 返回此 set 的部分视图,其元素严格小于 toElement。NavigableSet<E> headSet(E toElement)// 返回此 set 的部分视图,其元素小于(或等于,如果 inclusive 为 true)toElement。NavigableSet<E> headSet(E toElement, boolean inclusive)// 返回此 set 中严格大于给定元素的最小元素;如果不存在这样的元素,则返回 null。E higher(E e)// 如果此 set 不包含任何元素,则返回 true。boolean isEmpty()// 返回在此 set 的元素上以升序进行迭代的迭代器。Iterator<E> iterator()// 返回此 set 中当前最后一个(最高)元素。E last()// 返回此 set 中严格小于给定元素的最大元素;如果不存在这样的元素,则返回 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 中的元素数目。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源码(JDK1.7.0_40版本)
ConcurrentSkipListSet.java的完整源码如下:
1 /* 2 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21 * 22 * 23 */ 24 25 /* 26 * 27 * 28 * 29 * 30 * 31 * Written by Doug Lea with assistance from members of JCP JSR-166 32 * Expert Group and released to the public domain, as explained at 33 * http://creativecommons.org/publicdomain/zero/1.0/ 34 */ 35 36 package java.util.concurrent; 37 import java.util.*; 38 import sun.misc.Unsafe; 39 40 /** 41 * A scalable concurrent {@link NavigableSet} implementation based on 42 * a {@link ConcurrentSkipListMap}. The elements of the set are kept 43 * sorted according to their {@linkplain Comparable natural ordering}, 44 * or by a {@link Comparator} provided at set creation time, depending 45 * on which constructor is used. 46 * 47 * <p>This implementation provides expected average <i>log(n)</i> time 48 * cost for the <tt>contains</tt>, <tt>add</tt>, and <tt>remove</tt> 49 * operations and their variants. Insertion, removal, and access 50 * operations safely execute concurrently by multiple threads. 51 * Iterators are <i>weakly consistent</i>, returning elements 52 * reflecting the state of the set at some point at or since the 53 * creation of the iterator. They do <em>not</em> throw {@link 54 * ConcurrentModificationException}, and may proceed concurrently with 55 * other operations. Ascending ordered views and their iterators are 56 * faster than descending ones. 57 * 58 * <p>Beware that, unlike in most collections, the <tt>size</tt> 59 * method is <em>not</em> a constant-time operation. Because of the 60 * asynchronous nature of these sets, determining the current number 61 * of elements requires a traversal of the elements, and so may report 62 * inaccurate results if this collection is modified during traversal. 63 * Additionally, the bulk operations <tt>addAll</tt>, 64 * <tt>removeAll</tt>, <tt>retainAll</tt>, <tt>containsAll</tt>, 65 * <tt>equals</tt>, and <tt>toArray</tt> are <em>not</em> guaranteed 66 * to be performed atomically. For example, an iterator operating 67 * concurrently with an <tt>addAll</tt> operation might view only some 68 * of the added elements. 69 * 70 * <p>This class and its iterators implement all of the 71 * <em>optional</em> methods of the {@link Set} and {@link Iterator} 72 * interfaces. Like most other concurrent collection implementations, 73 * this class does not permit the use of <tt>null</tt> elements, 74 * because <tt>null</tt> arguments and return values cannot be reliably 75 * distinguished from the absence of elements. 76 * 77 * <p>This class is a member of the 78 * <a href="{@docRoot}/../technotes/guides/collections/index.html"> 79 * Java Collections Framework</a>. 80 * 81 * @author Doug Lea 82 * @param <E> the type of elements maintained by this set 83 * @since 1.6 84 */ 85 public class ConcurrentSkipListSet<E> 86 extends AbstractSet<E> 87 implements NavigableSet<E>, Cloneable, java.io.Serializable { 88 89 private static final long serialVersionUID = -2479143111061671589L; 90 91 /** 92 * The underlying map. Uses Boolean.TRUE as value for each 93 * element. This field is declared final for the sake of thread 94 * safety, which entails some ugliness in clone() 95 */ 96 private final ConcurrentNavigableMap<E,Object> m; 97 98 /** 99 * Constructs a new, empty set that orders its elements according to100 * their {@linkplain Comparable natural ordering}.101 */102 public ConcurrentSkipListSet() {103 m = new ConcurrentSkipListMap<E,Object>();104 }105 106 /**107 * Constructs a new, empty set that orders its elements according to108 * the specified comparator.109 *110 * @param comparator the comparator that will be used to order this set.111 * If <tt>null</tt>, the {@linkplain Comparable natural112 * ordering} of the elements will be used.113 */114 public ConcurrentSkipListSet(Comparator<? super E> comparator) {115 m = new ConcurrentSkipListMap<E,Object>(comparator);116 }117 118 /**119 * Constructs a new set containing the elements in the specified120 * collection, that orders its elements according to their121 * {@linkplain Comparable natural ordering}.122 *123 * @param c The elements that will comprise the new set124 * @throws ClassCastException if the elements in <tt>c</tt> are125 * not {@link Comparable}, or are not mutually comparable126 * @throws NullPointerException if the specified collection or any127 * of its elements are null128 */129 public ConcurrentSkipListSet(Collection<? extends E> c) {130 m = new ConcurrentSkipListMap<E,Object>();131 addAll(c);132 }133 134 /**135 * Constructs a new set containing the same elements and using the136 * same ordering as the specified sorted set.137 *138 * @param s sorted set whose elements will comprise the new set139 * @throws NullPointerException if the specified sorted set or any140 * of its elements are null141 */142 public ConcurrentSkipListSet(SortedSet<E> s) {143 m = new ConcurrentSkipListMap<E,Object>(s.comparator());144 addAll(s);145 }146 147 /**148 * For use by submaps149 */150 ConcurrentSkipListSet(ConcurrentNavigableMap<E,Object> m) {151 this.m = m;152 }153 154 /**155 * Returns a shallow copy of this <tt>ConcurrentSkipListSet</tt>156 * instance. (The elements themselves are not cloned.)157 *158 * @return a shallow copy of this set159 */160 public ConcurrentSkipListSet<E> clone() {161 ConcurrentSkipListSet<E> clone = null;162 try {163 clone = (ConcurrentSkipListSet<E>) super.clone();164 clone.setMap(new ConcurrentSkipListMap(m));165 } catch (CloneNotSupportedException e) {166 throw new InternalError();167 }168 169 return clone;170 }171 172 /* ---------------- Set operations -------------- */173 174 /**175 * Returns the number of elements in this set. If this set176 * contains more than <tt>Integer.MAX_VALUE</tt> elements, it177 * returns <tt>Integer.MAX_VALUE</tt>.178 *179 * <p>Beware that, unlike in most collections, this method is180 * <em>NOT</em> a constant-time operation. Because of the181 * asynchronous nature of these sets, determining the current182 * number of elements requires traversing them all to count them.183 * Additionally, it is possible for the size to change during184 * execution of this method, in which case the returned result185 * will be inaccurate. Thus, this method is typically not very186 * useful in concurrent applications.187 *188 * @return the number of elements in this set189 */190 public int size() {191 return m.size();192 }193 194 /**195 * Returns <tt>true</tt> if this set contains no elements.196 * @return <tt>true</tt> if this set contains no elements197 */198 public boolean isEmpty() {199 return m.isEmpty();200 }201 202 /**203 * Returns <tt>true</tt> if this set contains the specified element.204 * More formally, returns <tt>true</tt> if and only if this set205 * contains an element <tt>e</tt> such that <tt>o.equals(e)</tt>.206 *207 * @param o object to be checked for containment in this set208 * @return <tt>true</tt> if this set contains the specified element209 * @throws ClassCastException if the specified element cannot be210 * compared with the elements currently in this set211 * @throws NullPointerException if the specified element is null212 */213 public boolean contains(Object o) {214 return m.containsKey(o);215 }216 217 /**218 * Adds the specified element to this set if it is not already present.219 * More formally, adds the specified element <tt>e</tt> to this set if220 * the set contains no element <tt>e2</tt> such that <tt>e.equals(e2)</tt>.221 * If this set already contains the element, the call leaves the set222 * unchanged and returns <tt>false</tt>.223 *224 * @param e element to be added to this set225 * @return <tt>true</tt> if this set did not already contain the226 * specified element227 * @throws ClassCastException if <tt>e</tt> cannot be compared228 * with the elements currently in this set229 * @throws NullPointerException if the specified element is null230 */231 public boolean add(E e) {232 return m.putIfAbsent(e, Boolean.TRUE) == null;233 }234 235 /**236 * Removes the specified element from this set if it is present.237 * More formally, removes an element <tt>e</tt> such that238 * <tt>o.equals(e)</tt>, if this set contains such an element.239 * Returns <tt>true</tt> if this set contained the element (or240 * equivalently, if this set changed as a result of the call).241 * (This set will not contain the element once the call returns.)242 *243 * @param o object to be removed from this set, if present244 * @return <tt>true</tt> if this set contained the specified element245 * @throws ClassCastException if <tt>o</tt> cannot be compared246 * with the elements currently in this set247 * @throws NullPointerException if the specified element is null248 */249 public boolean remove(Object o) {250 return m.remove(o, Boolean.TRUE);251 }252 253 /**254 * Removes all of the elements from this set.255 */256 public void clear() {257 m.clear();258 }259 260 /**261 * Returns an iterator over the elements in this set in ascending order.262 *263 * @return an iterator over the elements in this set in ascending order264 */265 public Iterator<E> iterator() {266 return m.navigableKeySet().iterator();267 }268 269 /**270 * Returns an iterator over the elements in this set in descending order.271 *272 * @return an iterator over the elements in this set in descending order273 */274 public Iterator<E> descendingIterator() {275 return m.descendingKeySet().iterator();276 }277 278 279 /* ---------------- AbstractSet Overrides -------------- */280 281 /**282 * Compares the specified object with this set for equality. Returns283 * <tt>true</tt> if the specified object is also a set, the two sets284 * have the same size, and every member of the specified set is285 * contained in this set (or equivalently, every member of this set is286 * contained in the specified set). This definition ensures that the287 * equals method works properly across different implementations of the288 * set interface.289 *290 * @param o the object to be compared for equality with this set291 * @return <tt>true</tt> if the specified object is equal to this set292 */293 public boolean equals(Object o) {294 // Override AbstractSet version to avoid calling size()295 if (o == this)296 return true;297 if (!(o instanceof Set))298 return false;299 Collection<?> c = (Collection<?>) o;300 try {301 return containsAll(c) && c.containsAll(this);302 } catch (ClassCastException unused) {303 return false;304 } catch (NullPointerException unused) {305 return false;306 }307 }308 309 /**310 * Removes from this set all of its elements that are contained in311 * the specified collection. If the specified collection is also312 * a set, this operation effectively modifies this set so that its313 * value is the <i>asymmetric set difference</i> of the two sets.314 *315 * @param c collection containing elements to be removed from this set316 * @return <tt>true</tt> if this set changed as a result of the call317 * @throws ClassCastException if the types of one or more elements in this318 * set are incompatible with the specified collection319 * @throws NullPointerException if the specified collection or any320 * of its elements are null321 */322 public boolean removeAll(Collection<?> c) {323 // Override AbstractSet version to avoid unnecessary call to size()324 boolean modified = false;325 for (Iterator<?> i = c.iterator(); i.hasNext(); )326 if (remove(i.next()))327 modified = true;328 return modified;329 }330 331 /* ---------------- Relational operations -------------- */332 333 /**334 * @throws ClassCastException {@inheritDoc}335 * @throws NullPointerException if the specified element is null336 */337 public E lower(E e) {338 return m.lowerKey(e);339 }340 341 /**342 * @throws ClassCastException {@inheritDoc}343 * @throws NullPointerException if the specified element is null344 */345 public E floor(E e) {346 return m.floorKey(e);347 }348 349 /**350 * @throws ClassCastException {@inheritDoc}351 * @throws NullPointerException if the specified element is null352 */353 public E ceiling(E e) {354 return m.ceilingKey(e);355 }356 357 /**358 * @throws ClassCastException {@inheritDoc}359 * @throws NullPointerException if the specified element is null360 */361 public E higher(E e) {362 return m.higherKey(e);363 }364 365 public E pollFirst() {366 Map.Entry<E,Object> e = m.pollFirstEntry();367 return (e == null) ? null : e.getKey();368 }369 370 public E pollLast() {371 Map.Entry<E,Object> e = m.pollLastEntry();372 return (e == null) ? null : e.getKey();373 }374 375 376 /* ---------------- SortedSet operations -------------- */377 378 379 public Comparator<? super E> comparator() {380 return m.comparator();381 }382 383 /**384 * @throws NoSuchElementException {@inheritDoc}385 */386 public E first() {387 return m.firstKey();388 }389 390 /**391 * @throws NoSuchElementException {@inheritDoc}392 */393 public E last() {394 return m.lastKey();395 }396 397 /**398 * @throws ClassCastException {@inheritDoc}399 * @throws NullPointerException if {@code fromElement} or400 * {@code toElement} is null401 * @throws IllegalArgumentException {@inheritDoc}402 */403 public NavigableSet<E> subSet(E fromElement,404 boolean fromInclusive,405 E toElement,406 boolean toInclusive) {407 return new ConcurrentSkipListSet<E>408 (m.subMap(fromElement, fromInclusive,409 toElement, toInclusive));410 }411 412 /**413 * @throws ClassCastException {@inheritDoc}414 * @throws NullPointerException if {@code toElement} is null415 * @throws IllegalArgumentException {@inheritDoc}416 */417 public NavigableSet<E> headSet(E toElement, boolean inclusive) {418 return new ConcurrentSkipListSet<E>(m.headMap(toElement, inclusive));419 }420 421 /**422 * @throws ClassCastException {@inheritDoc}423 * @throws NullPointerException if {@code fromElement} is null424 * @throws IllegalArgumentException {@inheritDoc}425 */426 public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {427 return new ConcurrentSkipListSet<E>(m.tailMap(fromElement, inclusive));428 }429 430 /**431 * @throws ClassCastException {@inheritDoc}432 * @throws NullPointerException if {@code fromElement} or433 * {@code toElement} is null434 * @throws IllegalArgumentException {@inheritDoc}435 */436 public NavigableSet<E> subSet(E fromElement, E toElement) {437 return subSet(fromElement, true, toElement, false);438 }439 440 /**441 * @throws ClassCastException {@inheritDoc}442 * @throws NullPointerException if {@code toElement} is null443 * @throws IllegalArgumentException {@inheritDoc}444 */445 public NavigableSet<E> headSet(E toElement) {446 return headSet(toElement, false);447 }448 449 /**450 * @throws ClassCastException {@inheritDoc}451 * @throws NullPointerException if {@code fromElement} is null452 * @throws IllegalArgumentException {@inheritDoc}453 */454 public NavigableSet<E> tailSet(E fromElement) {455 return tailSet(fromElement, true);456 }457 458 /**459 * Returns a reverse order view of the elements contained in this set.460 * The descending set is backed by this set, so changes to the set are461 * reflected in the descending set, and vice-versa.462 *463 * <p>The returned set has an ordering equivalent to464 * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.465 * The expression {@code s.descendingSet().descendingSet()} returns a466 * view of {@code s} essentially equivalent to {@code s}.467 *468 * @return a reverse order view of this set469 */470 public NavigableSet<E> descendingSet() {471 return new ConcurrentSkipListSet(m.descendingMap());472 }473 474 // Support for resetting map in clone475 private void setMap(ConcurrentNavigableMap<E,Object> map) {476 UNSAFE.putObjectVolatile(this, mapOffset, map);477 }478 479 private static final sun.misc.Unsafe UNSAFE;480 private static final long mapOffset;481 static {482 try {483 UNSAFE = sun.misc.Unsafe.getUnsafe();484 Class k = ConcurrentSkipListSet.class;485 mapOffset = UNSAFE.objectFieldOffset486 (k.getDeclaredField("m"));487 } catch (Exception e) {488 throw new Error(e);489 }490 }491 }
ConcurrentSkipListSet是通过ConcurrentSkipListMap实现的,它的接口基本上都是通过调用ConcurrentSkipListMap接口来实现的。这里就不再对它的源码进行分析了。
ConcurrentSkipListSet示例
1 import java.util.*; 2 import java.util.concurrent.*; 3 4 /* 5 * ConcurrentSkipListSet是“线程安全”的集合,而TreeSet是非线程安全的。 6 * 7 * 下面是“多个线程同时操作并且遍历集合set”的示例 8 * (01) 当set是ConcurrentSkipListSet对象时,程序能正常运行。 9 * (02) 当set是TreeSet对象时,程序会产生ConcurrentModificationException异常。10 *11 * @author skywang12 */13 public class ConcurrentSkipListSetDemo1 {14 15 // TODO: set是TreeSet对象时,程序会出错。16 //private static Set<String> set = new TreeSet<String>();17 private static Set<String> set = new ConcurrentSkipListSet<String>();18 public static void main(String[] args) {19 20 // 同时启动两个线程对set进行操作!21 new MyThread("a").start();22 new MyThread("b").start();23 }24 25 private static void printAll() {26 String value = null;27 Iterator iter = set.iterator();28 while(iter.hasNext()) {29 value = (String)iter.next();30 System.out.print(value+", ");31 }32 System.out.println();33 }34 35 private static class MyThread extends Thread {36 MyThread(String name) {37 super(name);38 }39 @Override40 public void run() {41 int i = 0;42 while (i++ < 10) {43 // “线程名” + "序号"44 String val = Thread.currentThread().getName() + (i%6);45 set.add(val);46 // 通过“Iterator”遍历set。47 printAll();48 }49 }50 }51 }
(某一次)运行结果:
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,
结果说明:
示例程序中,启动两个线程(线程a和线程b)分别对ConcurrentSkipListSet进行操作。以线程a而言,它会先获取“线程名”+“序号”,然后将该字符串添加到ConcurrentSkipListSet集合中;接着,遍历并输出集合中的全部元素。 线程b的操作和线程a一样,只不过线程b的名字和线程a的名字不同。
当set是ConcurrentSkipListSet对象时,程序能正常运行。如果将set改为TreeSet时,程序会产生ConcurrentModificationException异常。
- Java多线程系列--“JUC集合”06之 ConcurrentSkipListSet
- Java多线程系列--“JUC集合”06之 ConcurrentSkipListSet
- Java多线程系列--“JUC集合”06之 ConcurrentSkipListSet
- JUC集合-06之 ConcurrentSkipListSet
- Java多线程系列--“JUC集合”
- JUC集合--ConcurrentSkipListSet
- Java多线程系列--“JUC集合”04之 ConcurrentHashMap
- Java多线程系列--“JUC集合”01之 框架
- Java多线程系列--“JUC集合”01之 框架
- Java多线程系列--“JUC集合”02之 CopyOnWriteArrayList
- Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet
- Java多线程系列--“JUC集合”04之 ConcurrentHashMap
- Java多线程系列--“JUC集合”01之 框架
- Java多线程系列--“JUC集合”02之 CopyOnWriteArrayList
- Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet
- Java多线程系列--“JUC集合”04之 ConcurrentHashMap
- Java多线程系列--“JUC集合”05之 ConcurrentSkipListMap
- Java多线程系列--“JUC集合”07之 ArrayBlockingQueue
- wow.js中各种特效对应的类名
- android存储五个方法
- 防护比特币病毒,关闭相应端口步骤
- kafka (一)
- Oracle笔记(七) 数据更新、事务处理、数据伪列
- Java多线程系列--“JUC集合”06之 ConcurrentSkipListSet
- 阻止按空格键页面下拉
- 双城记 A Tale of Two Cities
- js实现限时抢倒计时
- Java多线程系列--“JUC集合”07之 ArrayBlockingQueue
- Oracle笔记(八) 复杂查询及总结
- PNG文件结构分析 ---Png解析
- SylixOS中AHCI驱动框架分析
- C++中的类,类中定义该类的指针的用途