From e788d9880921f5d35c9df7182cb5d03d88312300 Mon Sep 17 00:00:00 2001 From: thatwhy <843279946@qq.com> Date: Sun, 5 Jan 2020 16:25:47 +0800 Subject: [PATCH] 057-week_o4 --- week_04/57/ArrayBlockingQueue-057.txt | 268 ++++++++++++++++++++ week_04/57/ConcurrentHashMap-057.txt | 272 ++++++++++++++++++++ week_04/57/ConcurrentLinkedQueue-057.txt | 306 +++++++++++++++++++++++ week_04/57/CopyOnWriteArrayList-057.txt | 211 ++++++++++++++++ week_04/57/DelayQueue-057.txt | 219 ++++++++++++++++ 5 files changed, 1276 insertions(+) create mode 100644 week_04/57/ArrayBlockingQueue-057.txt create mode 100644 week_04/57/ConcurrentHashMap-057.txt create mode 100644 week_04/57/ConcurrentLinkedQueue-057.txt create mode 100644 week_04/57/CopyOnWriteArrayList-057.txt create mode 100644 week_04/57/DelayQueue-057.txt diff --git a/week_04/57/ArrayBlockingQueue-057.txt b/week_04/57/ArrayBlockingQueue-057.txt new file mode 100644 index 0000000..a40da80 --- /dev/null +++ b/week_04/57/ArrayBlockingQueue-057.txt @@ -0,0 +1,268 @@ +CopyOnWriteArrayList:写时复制,并发的ArrayList,用来代替在并发下的ArrayList, +在对元素有变动操作的时候,会进行加锁,并且复制一个新的list出来进行操作,最后返回这个新的list,不影响读的操作 +一、构造方法 + +1.创建一个空列表。 + public CopyOnWriteArrayList() { + setArray(new Object[0]); + } +2.按照 Collection 的迭代器返回元素的顺序,创建一个包含指定 Collection 的元素的列表。 + public CopyOnWriteArrayList(Collection c) { + Object[] elements; + if (c.getClass() == CopyOnWriteArrayList.class) + elements = ((CopyOnWriteArrayList)c).getArray(); + else { + elements = c.toArray(); + // c.toArray might (incorrectly) not return Object[] (see 6260652) + if (elements.getClass() != Object[].class) + elements = Arrays.copyOf(elements, elements.length, Object[].class); + } + setArray(elements); + } + +3.创建一个新的 CopyOnWriteArrayList,它保持给定数组的副本。 + public CopyOnWriteArrayList(E[] toCopyIn) { + setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class)); + } + +4.比较方法 这个写法有点灵活,算是学到了 + private static boolean eq(Object o1, Object o2) { + return (o1 == null) ? o2 == null : o1.equals(o2); + } +5.返回元素索引 + private static int indexOf(Object o, Object[] elements, + int index, int fence) { + if (o == null) { + for (int i = index; i < fence; i++) + if (elements[i] == null) + return i; + } else { + for (int i = index; i < fence; i++) + if (o.equals(elements[i])) + return i; + } + return -1; + } + +6.contains和indexOf其实都是凋的indexOf(Object o, Object[] elements,int index, int fence)方法 + public boolean contains(Object o) { + Object[] elements = getArray(); + return indexOf(o, elements, 0, elements.length) >= 0; + } + + /** + * {@inheritDoc} + */ + public int indexOf(Object o) { + Object[] elements = getArray(); + return indexOf(o, elements, 0, elements.length); + } + public int indexOf(E e, int index) { + Object[] elements = getArray(); + return indexOf(e, elements, index, elements.length); + } +7.转数组方法 + public Object[] toArray() { + Object[] elements = getArray(); + return Arrays.copyOf(elements, elements.length); + } + public T[] toArray(T a[]) { + Object[] elements = getArray(); + int len = elements.length; + if (a.length < len) + return (T[]) Arrays.copyOf(elements, len, a.getClass()); + else { + System.arraycopy(elements, 0, a, 0, len); + if (a.length > len) + a[len] = null; + return a; + } + } +8.set无需加锁,get、add、remove等对集合元素有变动操作的需要加锁 + public E set(int index, E element) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + Object[] elements = getArray(); + E oldValue = get(elements, index); + + if (oldValue != element) { + int len = elements.length; + Object[] newElements = Arrays.copyOf(elements, len); + newElements[index] = element; + setArray(newElements); + } else { + // Not quite a no-op; ensures volatile write semantics + setArray(elements); + } + return oldValue; + } finally { + lock.unlock(); + } + } +9. public boolean add(E e) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + Object[] elements = getArray(); + int len = elements.length; + Object[] newElements = Arrays.copyOf(elements, len + 1); + newElements[len] = e; + setArray(newElements); + return true; + } finally { + lock.unlock(); + } + } + +10. public E remove(int index) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + Object[] elements = getArray(); + int len = elements.length; + E oldValue = get(elements, index); + int numMoved = len - index - 1; + if (numMoved == 0) + setArray(Arrays.copyOf(elements, len - 1)); + else { + Object[] newElements = new Object[len - 1]; + System.arraycopy(elements, 0, newElements, 0, index); + System.arraycopy(elements, index + 1, newElements, index, + numMoved); + setArray(newElements); + } + return oldValue; + } finally { + lock.unlock(); + } + } + +11. void removeRange(int fromIndex, int toIndex) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + Object[] elements = getArray(); + int len = elements.length; + + if (fromIndex < 0 || toIndex > len || toIndex < fromIndex) + throw new IndexOutOfBoundsException(); + int newlen = len - (toIndex - fromIndex); + int numMoved = len - toIndex; + if (numMoved == 0) + setArray(Arrays.copyOf(elements, newlen)); + else { + Object[] newElements = new Object[newlen]; + System.arraycopy(elements, 0, newElements, 0, fromIndex); + System.arraycopy(elements, toIndex, newElements, + fromIndex, numMoved); + setArray(newElements); + } + } finally { + lock.unlock(); + } + } +12. 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 < common; 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(); + } + } +13. 只保留此 Collection 中包含在指定 Collection 中的元素(可选操作)。 + 换句话说,从此 Collection 中移除所有未包含在指定 Collection 中的元素。 + public boolean retainAll(Collection c) { + if (c == null) throw new NullPointerException(); + final ReentrantLock lock = this.lock; + lock.lock(); + try { + Object[] elements = getArray(); + int len = elements.length; + if (len != 0) { + // temp array holds those elements we know we want to keep + int newlen = 0; + Object[] temp = new Object[len]; + for (int i = 0; i < len; ++i) { + Object element = elements[i]; + if (c.contains(element)) + temp[newlen++] = element; + } + if (newlen != len) { + setArray(Arrays.copyOf(temp, newlen)); + return true; + } + } + return false; + } finally { + lock.unlock(); + } + } + +14. 按照指定 Collection 的迭代器返回元素的顺序,将指定 Collection 中尚未包含在此列表中的所有元素追加列表的尾部。 + public int addAllAbsent(Collection c) { + Object[] cs = c.toArray(); + if (cs.length == 0) + return 0; + final ReentrantLock lock = this.lock; + lock.lock(); + try { + Object[] elements = getArray(); + int len = elements.length; + int added = 0; + // uniquify and compact elements in cs + for (int i = 0; i < cs.length; ++i) { + Object e = cs[i]; + if (indexOf(e, elements, 0, len) < 0 && + indexOf(e, cs, 0, added) < 0) + cs[added++] = e; + } + if (added > 0) { + Object[] newElements = Arrays.copyOf(elements, len + added); + System.arraycopy(cs, 0, newElements, len, added); + setArray(newElements); + } + return added; + } finally { + lock.unlock(); + } + } +15. 直接赋值一个空的数组 + public void clear() { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + setArray(new Object[0]); + } finally { + lock.unlock(); + } + } +16. 排序 + public void sort(Comparator c) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + Object[] elements = getArray(); + Object[] newElements = Arrays.copyOf(elements, elements.length); + @SuppressWarnings("unchecked") E[] es = (E[])newElements; + Arrays.sort(es, c); + setArray(newElements); + } finally { + lock.unlock(); + } + } \ No newline at end of file diff --git a/week_04/57/ConcurrentHashMap-057.txt b/week_04/57/ConcurrentHashMap-057.txt new file mode 100644 index 0000000..f39893e --- /dev/null +++ b/week_04/57/ConcurrentHashMap-057.txt @@ -0,0 +1,272 @@ +并发的HashMap,用来替代并发情况下的Hashmap +基本初始化参数信息同HashMap +一、构造方法 +1. public ConcurrentHashMap() { + } + + public ConcurrentHashMap(int initialCapacity) { + if (initialCapacity < 0) + throw new IllegalArgumentException(); + int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ? + MAXIMUM_CAPACITY : + tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1)); + this.sizeCtl = cap; + } + public ConcurrentHashMap(Map m) { + this.sizeCtl = DEFAULT_CAPACITY; + putAll(m); + } + + public ConcurrentHashMap(int initialCapacity, float loadFactor) { + this(initialCapacity, loadFactor, 1); + } + public ConcurrentHashMap(int initialCapacity, + float loadFactor, int concurrencyLevel) { + if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0) + throw new IllegalArgumentException(); + if (initialCapacity < concurrencyLevel) // Use at least as many bins + initialCapacity = concurrencyLevel; // as estimated threads + long size = (long)(1.0 + (long)initialCapacity / loadFactor); + int cap = (size >= (long)MAXIMUM_CAPACITY) ? + MAXIMUM_CAPACITY : tableSizeFor((int)size); + this.sizeCtl = cap; + } +2. size最小为0,最大为Integer.MAX_VALUE + public int size() { + long n = sumCount(); + return ((n < 0L) ? 0 : + (n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE : + (int)n); + } + +3.get + public V get(Object key) { + Node[] tab; Node e, p; int n, eh; K ek; + int h = spread(key.hashCode()); + if ((tab = table) != null && (n = tab.length) > 0 && + (e = tabAt(tab, (n - 1) & h)) != null) { + if ((eh = e.hash) == h) { + if ((ek = e.key) == key || (ek != null && key.equals(ek))) + return e.val; + } + else if (eh < 0) + return (p = e.find(h, key)) != null ? p.val : null; + while ((e = e.next) != null) { + if (e.hash == h && + ((ek = e.key) == key || (ek != null && key.equals(ek)))) + return e.val; + } + } + return null; + } + +4.put,有点复杂,并不是很懂 +public V put(K key, V value) { + return putVal(key, value, false); + } + + /** Implementation for put and putIfAbsent */ + final V putVal(K key, V value, boolean onlyIfAbsent) { + if (key == null || value == null) throw new NullPointerException(); + int hash = spread(key.hashCode()); + int binCount = 0; + for (Node[] tab = table;;) { + Node f; int n, i, fh; + if (tab == null || (n = tab.length) == 0) + tab = initTable(); + else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) { + if (casTabAt(tab, i, null, + new Node(hash, key, value, null))) + break; // no lock when adding to empty bin + } + else if ((fh = f.hash) == MOVED) + tab = helpTransfer(tab, f); + else { + V oldVal = null; + synchronized (f) { + if (tabAt(tab, i) == f) { + if (fh >= 0) { + binCount = 1; + for (Node e = f;; ++binCount) { + K ek; + if (e.hash == hash && + ((ek = e.key) == key || + (ek != null && key.equals(ek)))) { + oldVal = e.val; + if (!onlyIfAbsent) + e.val = value; + break; + } + Node pred = e; + if ((e = e.next) == null) { + pred.next = new Node(hash, key, + value, null); + break; + } + } + } + else if (f instanceof TreeBin) { + Node p; + binCount = 2; + if ((p = ((TreeBin)f).putTreeVal(hash, key, + value)) != null) { + oldVal = p.val; + if (!onlyIfAbsent) + p.val = value; + } + } + } + } + if (binCount != 0) { + if (binCount >= TREEIFY_THRESHOLD) + treeifyBin(tab, i); + if (oldVal != null) + return oldVal; + break; + } + } + } + addCount(1L, binCount); + return null; + } +5. + public V remove(Object key) { + return replaceNode(key, null, null); + } + + final V replaceNode(Object key, V value, Object cv) { + int hash = spread(key.hashCode()); + for (Node[] tab = table;;) { + Node f; int n, i, fh; + if (tab == null || (n = tab.length) == 0 || + (f = tabAt(tab, i = (n - 1) & hash)) == null) + break; + else if ((fh = f.hash) == MOVED) + tab = helpTransfer(tab, f); + else { + V oldVal = null; + boolean validated = false; + synchronized (f) { + if (tabAt(tab, i) == f) { + if (fh >= 0) { + validated = true; + for (Node e = f, pred = null;;) { + K ek; + if (e.hash == hash && + ((ek = e.key) == key || + (ek != null && key.equals(ek)))) { + V ev = e.val; + if (cv == null || cv == ev || + (ev != null && cv.equals(ev))) { + oldVal = ev; + if (value != null) + e.val = value; + else if (pred != null) + pred.next = e.next; + else + setTabAt(tab, i, e.next); + } + break; + } + pred = e; + if ((e = e.next) == null) + break; + } + } + else if (f instanceof TreeBin) { + validated = true; + TreeBin t = (TreeBin)f; + TreeNode r, p; + if ((r = t.root) != null && + (p = r.findTreeNode(hash, key, null)) != null) { + V pv = p.val; + if (cv == null || cv == pv || + (pv != null && cv.equals(pv))) { + oldVal = pv; + if (value != null) + p.val = value; + else if (t.removeTreeNode(p)) + setTabAt(tab, i, untreeify(t.first)); + } + } + } + } + } + if (validated) { + if (oldVal != null) { + if (value == null) + addCount(-1L, -1); + return oldVal; + } + break; + } + } + } + return null; + } + +6. + public void clear() { + long delta = 0L; // negative number of deletions + int i = 0; + Node[] tab = table; + while (tab != null && i < tab.length) { + int fh; + Node f = tabAt(tab, i); + if (f == null) + ++i; + else if ((fh = f.hash) == MOVED) { + tab = helpTransfer(tab, f); + i = 0; // restart + } + else { + synchronized (f) { + if (tabAt(tab, i) == f) { + Node p = (fh >= 0 ? f : + (f instanceof TreeBin) ? + ((TreeBin)f).first : null); + while (p != null) { + --delta; + p = p.next; + } + setTabAt(tab, i++, null); + } + } + } + } + if (delta != 0L) + addCount(delta, -1); + } +7.equals方法 + public boolean equals(Object o) { + if (o != this) { + if (!(o instanceof Map)) + return false; + Map m = (Map) o; + Node[] t; + int f = (t = table) == null ? 0 : t.length; + Traverser it = new Traverser(t, f, 0, f); + for (Node p; (p = it.advance()) != null; ) { + V val = p.val; + Object v = m.get(p.key); + if (v == null || (v != val && !v.equals(val))) + return false; + } + for (Map.Entry e : m.entrySet()) { + Object mk, mv, v; + if ((mk = e.getKey()) == null || + (mv = e.getValue()) == null || + (v = get(mk)) == null || + (mv != v && !mv.equals(v))) + return false; + } + } + return true; + } + +8. + public V replace(K key, V value) { + if (key == null || value == null) + throw new NullPointerException(); + return replaceNode(key, value, null); + } \ No newline at end of file diff --git a/week_04/57/ConcurrentLinkedQueue-057.txt b/week_04/57/ConcurrentLinkedQueue-057.txt new file mode 100644 index 0000000..afe5293 --- /dev/null +++ b/week_04/57/ConcurrentLinkedQueue-057.txt @@ -0,0 +1,306 @@ +数组阻塞队列 +一、构造方法 + public ArrayBlockingQueue(int capacity) { + this(capacity, false); + } + public ArrayBlockingQueue(int capacity, boolean fair) { + if (capacity <= 0) + throw new IllegalArgumentException(); + this.items = new Object[capacity]; + lock = new ReentrantLock(fair); + notEmpty = lock.newCondition(); + notFull = lock.newCondition(); + } + public ArrayBlockingQueue(int capacity, boolean fair, + Collection c) { + this(capacity, fair); + + final ReentrantLock lock = this.lock; + lock.lock(); // Lock only for visibility, not mutual exclusion + try { + int i = 0; + try { + for (E e : c) { + checkNotNull(e); + items[i++] = e; + } + } catch (ArrayIndexOutOfBoundsException ex) { + throw new IllegalArgumentException(); + } + count = i; + putIndex = (i == capacity) ? 0 : i; + } finally { + lock.unlock(); + } + } +二、方法 +1. + public boolean add(E e) { + return super.add(e); + } + public boolean add(E e) { + if (offer(e)) + return true; + else + throw new IllegalStateException("Queue full"); + } +2.将指定的元素插入到此队列的尾部(如果可能),如果此队列已满,则立即返回。 + public boolean offer(E e) { + checkNotNull(e); + final ReentrantLock lock = this.lock; + lock.lock(); + try { + if (count == items.length) + return false; + else { + enqueue(e); + return true; + } + } finally { + lock.unlock(); + } + } +3.将指定的元素添加到此队列的尾部,如果必要,将等待可用的空间。 + public void put(E e) throws InterruptedException { + checkNotNull(e); + final ReentrantLock lock = this.lock; + lock.lockInterruptibly(); + try { + while (count == items.length) + notFull.await(); + enqueue(e); + } finally { + lock.unlock(); + } + } +4.将指定的元素插入到此队列的尾部,如果没有可用空间,将等待指定的等待时间(如果有必要)。 + public boolean offer(E e, long timeout, TimeUnit unit) + throws InterruptedException { + + checkNotNull(e); + long nanos = unit.toNanos(timeout); + final ReentrantLock lock = this.lock; + lock.lockInterruptibly(); + try { + while (count == items.length) { + if (nanos <= 0) + return false; + nanos = notFull.awaitNanos(nanos); + } + enqueue(e); + return true; + } finally { + lock.unlock(); + } + } +5.检索并移除此队列的头,如果此队列为空,则返回 null。 + public E poll() { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + return (count == 0) ? null : dequeue(); + } finally { + lock.unlock(); + } + } +6.检索并移除此队列的头部,如果此队列不存在任何元素,则一直等待。 + public E take() throws InterruptedException { + final ReentrantLock lock = this.lock; + lock.lockInterruptibly(); + try { + while (count == 0) + notEmpty.await(); + return dequeue(); + } finally { + lock.unlock(); + } + } +7.从接口 BlockingQueue 复制的描述 + 检索并移除此队列的头部,如果此队列中没有任何元素,则等待指定等待的时间(如果有必要)。 + public E poll(long timeout, TimeUnit unit) throws InterruptedException { + long nanos = unit.toNanos(timeout); + final ReentrantLock lock = this.lock; + lock.lockInterruptibly(); + try { + while (count == 0) { + if (nanos <= 0) + return null; + nanos = notEmpty.awaitNanos(nanos); + } + return dequeue(); + } finally { + lock.unlock(); + } + } +8.检索,但是不移除此队列的头,如果此队列为空,则返回 null。 + public E peek() { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + return itemAt(takeIndex); // null when queue is empty + } finally { + lock.unlock(); + } + } +9.返回此队列中元素的数量。 + public int size() { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + return count; + } finally { + lock.unlock(); + } + } +10. + public int remainingCapacity() { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + return items.length - count; + } finally { + lock.unlock(); + } + } +11. + public boolean remove(Object o) { + if (o == null) return false; + final Object[] items = this.items; + final ReentrantLock lock = this.lock; + lock.lock(); + try { + if (count > 0) { + final int putIndex = this.putIndex; + int i = takeIndex; + do { + if (o.equals(items[i])) { + removeAt(i); + return true; + } + if (++i == items.length) + i = 0; + } while (i != putIndex); + } + return false; + } finally { + lock.unlock(); + } + } +12. + public boolean contains(Object o) { + if (o == null) return false; + final Object[] items = this.items; + final ReentrantLock lock = this.lock; + lock.lock(); + try { + if (count > 0) { + final int putIndex = this.putIndex; + int i = takeIndex; + do { + if (o.equals(items[i])) + return true; + if (++i == items.length) + i = 0; + } while (i != putIndex); + } + return false; + } finally { + lock.unlock(); + } + } +13. + public Object[] toArray() { + Object[] a; + final ReentrantLock lock = this.lock; + lock.lock(); + try { + final int count = this.count; + a = new Object[count]; + int n = items.length - takeIndex; + if (count <= n) + System.arraycopy(items, takeIndex, a, 0, count); + else { + System.arraycopy(items, takeIndex, a, 0, n); + System.arraycopy(items, 0, a, n, count - n); + } + } finally { + lock.unlock(); + } + return a; + } +14. + public void clear() { + final Object[] items = this.items; + final ReentrantLock lock = this.lock; + lock.lock(); + try { + int k = count; + if (k > 0) { + final int putIndex = this.putIndex; + int i = takeIndex; + do { + items[i] = null; + if (++i == items.length) + i = 0; + } while (i != putIndex); + takeIndex = putIndex; + count = 0; + if (itrs != null) + itrs.queueIsEmpty(); + for (; k > 0 && lock.hasWaiters(notFull); k--) + notFull.signal(); + } + } finally { + lock.unlock(); + } + } +15.移除此队列中所有可用的元素,并将它们添加到给定 collection 中。此操作可能比反复轮询此队列更有效。 +在试图向 c 集合中 add 元素没有成功时,可能导致在抛出相关异常时,元素会同时在两个 collection 中出现, +或者在其中一个 collection 中出现,也可能在两个 collection 中都不出现。如果试图将一个队列放入自身队列中, +则会导致 IllegalArgumentException 异常。此外,如果正在进行此操作时修改指定的 collection,则此操作行为是不确定的。 + public int drainTo(Collection c) { + return drainTo(c, Integer.MAX_VALUE); + } + public int drainTo(Collection c, int maxElements) { + checkNotNull(c); + if (c == this) + throw new IllegalArgumentException(); + if (maxElements <= 0) + return 0; + final Object[] items = this.items; + final ReentrantLock lock = this.lock; + lock.lock(); + try { + int n = Math.min(maxElements, count); + int take = takeIndex; + int i = 0; + try { + while (i < n) { + @SuppressWarnings("unchecked") + E x = (E) items[take]; + c.add(x); + items[take] = null; + if (++take == items.length) + take = 0; + i++; + } + return n; + } finally { + // Restore invariants even if c.add() threw + if (i > 0) { + count -= i; + takeIndex = take; + if (itrs != null) { + if (count == 0) + itrs.queueIsEmpty(); + else if (i > take) + itrs.takeIndexWrapped(); + } + for (; i > 0 && lock.hasWaiters(notFull); i--) + notFull.signal(); + } + } + } finally { + lock.unlock(); + } + } \ No newline at end of file diff --git a/week_04/57/CopyOnWriteArrayList-057.txt b/week_04/57/CopyOnWriteArrayList-057.txt new file mode 100644 index 0000000..40381cd --- /dev/null +++ b/week_04/57/CopyOnWriteArrayList-057.txt @@ -0,0 +1,211 @@ +一、构造方法 +1. + public ConcurrentLinkedQueue() { + head = tail = new Node(null); + } +2. + public ConcurrentLinkedQueue(Collection c) { + Node h = null, t = null; + for (E e : c) { + checkNotNull(e); + Node newNode = new Node(e); + if (h == null) + h = t = newNode; + else { + t.lazySetNext(newNode); + t = newNode; + } + } + if (h == null) + h = t = new Node(null); + head = h; + tail = t; + } + +二、方法 +1.将指定元素添加到此队列的尾部。 + public boolean add(E e) { + return offer(e); + } + 将指定元素插入到此队列的尾部。 + public boolean offer(E e) { + checkNotNull(e); + final Node newNode = new Node(e); + + for (Node t = tail, p = t;;) { + Node q = p.next; + if (q == null) { + // p is last node + if (p.casNext(null, newNode)) { + // Successful CAS is the linearization point + // for e to become an element of this queue, + // and for newNode to become "live". + if (p != t) // hop two nodes at a time + casTail(t, newNode); // Failure is OK. + return true; + } + // Lost CAS race to another thread; re-read next + } + else if (p == q) + // We have fallen off list. If tail is unchanged, it + // will also be off-list, in which case we need to + // jump to head, from which all live nodes are always + // reachable. Else the new tail is a better bet. + p = (t != (t = tail)) ? t : head; + else + // Check for tail updates after two hops. + p = (p != t && t != (t = tail)) ? t : q; + } + } +2. + final Node succ(Node p) { + Node next = p.next; + return (p == next) ? head : next; + } +3.检索并移除此队列的头,如果此队列为空,则返回 null。 + public E poll() { + restartFromHead: + for (;;) { + for (Node h = head, p = h, q;;) { + E item = p.item; + + if (item != null && p.casItem(item, null)) { + // Successful CAS is the linearization point + // for item to be removed from this queue. + if (p != h) // hop two nodes at a time + updateHead(h, ((q = p.next) != null) ? q : p); + return item; + } + else if ((q = p.next) == null) { + updateHead(h, p); + return null; + } + else if (p == q) + continue restartFromHead; + else + p = q; + } + } + } +4.检索,但是不移除此队列的头,如果此队列为空,则返回 null。 + public E peek() { + restartFromHead: + for (;;) { + for (Node h = head, p = h, q;;) { + E item = p.item; + if (item != null || (q = p.next) == null) { + updateHead(h, p); + return item; + } + else if (p == q) + continue restartFromHead; + else + p = q; + } + } + } +5. + Node first() { + restartFromHead: + for (;;) { + for (Node h = head, p = h, q;;) { + boolean hasItem = (p.item != null); + if (hasItem || (q = p.next) == null) { + updateHead(h, p); + return hasItem ? p : null; + } + else if (p == q) + continue restartFromHead; + else + p = q; + } + } + } +6.返回此队列中的元素数量。如果此队列包含的元素数大于 Integer.MAX_VALUE,则返回 Integer.MAX_VALUE。 +需要小心的是,与大多数 collection 不同,此方法不是 一个固定时间的操作。 +由于这些队列的异步特性,确定当前的元素数需要进行一次花费 O(n) 时间的遍历。 + + public int size() { + int count = 0; + for (Node p = first(); p != null; p = succ(p)) + if (p.item != null) + // Collection.size() spec says to max out + if (++count == Integer.MAX_VALUE) + break; + return count; + } +7. + public boolean remove(Object o) { + if (o != null) { + Node next, pred = null; + for (Node p = first(); p != null; pred = p, p = next) { + boolean removed = false; + E item = p.item; + if (item != null) { + if (!o.equals(item)) { + next = succ(p); + continue; + } + removed = p.casItem(item, null); + } + + next = succ(p); + if (pred != null && next != null) // unlink + pred.casNext(p, next); + if (removed) + return true; + } + } + return false; + } +8. + public boolean addAll(Collection c) { + if (c == this) + // As historically specified in AbstractQueue#addAll + throw new IllegalArgumentException(); + + // Copy c into a private chain of Nodes + Node beginningOfTheEnd = null, last = null; + for (E e : c) { + checkNotNull(e); + Node newNode = new Node(e); + if (beginningOfTheEnd == null) + beginningOfTheEnd = last = newNode; + else { + last.lazySetNext(newNode); + last = newNode; + } + } + if (beginningOfTheEnd == null) + return false; + + // Atomically append the chain at the tail of this collection + for (Node t = tail, p = t;;) { + Node q = p.next; + if (q == null) { + // p is last node + if (p.casNext(null, beginningOfTheEnd)) { + // Successful CAS is the linearization point + // for all elements to be added to this queue. + if (!casTail(t, last)) { + // Try a little harder to update tail, + // since we may be adding many elements. + t = tail; + if (last.next == null) + casTail(t, last); + } + return true; + } + // Lost CAS race to another thread; re-read next + } + else if (p == q) + // We have fallen off list. If tail is unchanged, it + // will also be off-list, in which case we need to + // jump to head, from which all live nodes are always + // reachable. Else the new tail is a better bet. + p = (t != (t = tail)) ? t : head; + else + // Check for tail updates after two hops. + p = (p != t && t != (t = tail)) ? t : q; + } + } \ No newline at end of file diff --git a/week_04/57/DelayQueue-057.txt b/week_04/57/DelayQueue-057.txt new file mode 100644 index 0000000..651a17c --- /dev/null +++ b/week_04/57/DelayQueue-057.txt @@ -0,0 +1,219 @@ +Delayed 元素的一个无界阻塞队列,只有在延迟期满时才能从中提取元素。 +该队列的头部 是延迟期满后保存时间最长的 Delayed 元素。如果延迟都还没有期满, +则队列没有头部,并且 poll 将返回 null。当一个元素的 getDelay(TimeUnit.NANOSECONDS) +方法返回一个小于或等于零的值时,则出现期满。此队列不允许使用 null 元素。 +一、构造方法 +1. + public DelayQueue() {} +2. + public DelayQueue(Collection c) { + this.addAll(c); + } + +二、方法 +1. + public boolean add(E e) { + return offer(e); + } + 将指定元素插入到此延迟队列中。 + public boolean offer(E e) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + q.offer(e); + if (q.peek() == e) { + leader = null; + available.signal(); + } + return true; + } finally { + lock.unlock(); + } + } + +2.将指定元素添加到此延迟队列中。由于该队列是无界的,所以此方法永远不会阻塞。 + public void put(E e) { + offer(e); + } + public boolean offer(E e) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + q.offer(e); + if (q.peek() == e) { + leader = null; + available.signal(); + } + return true; + } finally { + lock.unlock(); + } + } +3.检索并移除此队列的头部,如果此队列不存在未到期延迟的元素,则返回 null。 + public E poll() { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + E first = q.peek(); + if (first == null || first.getDelay(NANOSECONDS) > 0) + return null; + else + return q.poll(); + } finally { + lock.unlock(); + } + } +4.检索并移除此队列的头部,如果此队列不存在未到期延迟的元素,则等待它。 + public E take() throws InterruptedException { + final ReentrantLock lock = this.lock; + lock.lockInterruptibly(); + try { + for (;;) { + E first = q.peek(); + if (first == null) + available.await(); + else { + long delay = first.getDelay(NANOSECONDS); + if (delay <= 0) + return q.poll(); + first = null; // don't retain ref while waiting + if (leader != null) + available.await(); + else { + Thread thisThread = Thread.currentThread(); + leader = thisThread; + try { + available.awaitNanos(delay); + } finally { + if (leader == thisThread) + leader = null; + } + } + } + } + } finally { + if (leader == null && q.peek() != null) + available.signal(); + lock.unlock(); + } + } +5.检索并移除此队列的头部,如果此队列不存在未到期延迟的元素,则在到达指定的等待时间之前,一直等待(如果有必要)。 + public E poll(long timeout, TimeUnit unit) throws InterruptedException { + long nanos = unit.toNanos(timeout); + final ReentrantLock lock = this.lock; + lock.lockInterruptibly(); + try { + for (;;) { + E first = q.peek(); + if (first == null) { + if (nanos <= 0) + return null; + else + nanos = available.awaitNanos(nanos); + } else { + long delay = first.getDelay(NANOSECONDS); + if (delay <= 0) + return q.poll(); + if (nanos <= 0) + return null; + first = null; // don't retain ref while waiting + if (nanos < delay || leader != null) + nanos = available.awaitNanos(nanos); + else { + Thread thisThread = Thread.currentThread(); + leader = thisThread; + try { + long timeLeft = available.awaitNanos(delay); + nanos -= delay - timeLeft; + } finally { + if (leader == thisThread) + leader = null; + } + } + } + } + } finally { + if (leader == null && q.peek() != null) + available.signal(); + lock.unlock(); + } + } +6.检索但不移除此队列的头部,如果此队列不存在未到期延迟的元素,则返回 null。 + public E peek() { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + return q.peek(); + } finally { + lock.unlock(); + } + } +7. + + private E peekExpired() { + // assert lock.isHeldByCurrentThread(); + E first = q.peek(); + return (first == null || first.getDelay(NANOSECONDS) > 0) ? + null : first; + } +8.移除此队列中所有可用的元素,并将它们添加到给定 collection 中。 +此操作可能比反复轮询此队列更有效。在试图向 c 集合中 add 元素没有成功时, +可能导致在抛出相关异常时,元素会同时在两个 collection 中出现, +或者在其中一个 collection 中出现,也可能在两个 collection 中都不出现。 +如果试图将一个队列放入自身队列中,则会导致 IllegalArgumentException 异常。 +此外,如果正在进行此操作时修改指定的 collection,则此操作行为是不确定的。 + public int drainTo(Collection c) { + if (c == null) + throw new NullPointerException(); + if (c == this) + throw new IllegalArgumentException(); + final ReentrantLock lock = this.lock; + lock.lock(); + try { + int n = 0; + for (E e; (e = peekExpired()) != null;) { + c.add(e); // In this order, in case add() throws. + q.poll(); + ++n; + } + return n; + } finally { + lock.unlock(); + } + } +9. + public int drainTo(Collection c, int maxElements) { + if (c == null) + throw new NullPointerException(); + if (c == this) + throw new IllegalArgumentException(); + if (maxElements <= 0) + return 0; + final ReentrantLock lock = this.lock; + lock.lock(); + try { + int n = 0; + for (E e; n < maxElements && (e = peekExpired()) != null;) { + c.add(e); // In this order, in case add() throws. + q.poll(); + ++n; + } + return n; + } finally { + lock.unlock(); + } + } +10.因为 DelayQueue 没有容量限制,所以它总是返回 Integer.MAX_VALUE + public int remainingCapacity() { + return Integer.MAX_VALUE; + } +11.加锁清楚 + public void clear() { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + q.clear(); + } finally { + lock.unlock(); + } + } \ No newline at end of file -- Gitee