弹出对象
DefaultHandle<T> pop() { int size = this.size; //先判断size是否==0 if (size == 0) { //从WeakOrderQueue中扫出对象放入elements数组中 if (!scavenge()) { return null; } size = this.size; if (size <= 0) { // double check, avoid races return null; } } //size减1 size --; DefaultHandle ret = elements[size]; elements[size] = null; // 因为我们已经将element [size]设置为null,所以在进行任何验证之前,我们还需要存储更新的大小。否则,当以后尝试再次弹出而之前未添加新元素时,我们可能会看到null值。 this.size = size; if (ret.lastRecycledId != ret.recycleId) { throw new IllegalStateException("recycled multiple times"); } ret.recycleId = 0; ret.lastRecycledId = 0; return ret; }
scavenge()
private boolean scavenge() { // continue an existing scavenge, if any if (scavengeSome()) { return true; } // reset our scavenge cursor prev = null; cursor = head; return false; } private boolean scavengeSome() { WeakOrderQueue prev; WeakOrderQueue cursor = this.cursor; //如果游标为空,设置游标=head if (cursor == null) { prev = null; cursor = head; //如果游标还是空,那么池中没有对象,返回false if (cursor == null) { return false; } } else { prev = this.prev; } boolean success = false; do { //WeakOrderQueue中的对象转换到elements数组中 if (cursor.transfer(this)) { success = true; break; } WeakOrderQueue next = cursor.getNext(); if (cursor.get() == null) { // If the thread associated with the queue is gone, unlink it, after // performing a volatile read to confirm there is no data left to collect. // We never unlink the first queue, as we don't want to synchronize on updating the head. if (cursor.hasFinalData()) { for (;;) { if (cursor.transfer(this)) { success = true; } else { break; } } } if (prev != null) { // Ensure we reclaim all space before dropping the WeakOrderQueue to be GC'ed. cursor.reclaimAllSpaceAndUnlink(); prev.setNext(next); } } else { prev = cursor; } cursor = next; } while (cursor != null && !success); this.prev = prev; this.cursor = cursor; return success; }
WeakOrderQueue.transfer(stack)
boolean transfer(Stack<?> dst) { //拿到第一个Link Link head = this.head.link; //为空则说明WorkQueue中无对象 if (head == null) { return false; } //判断Link中对象是否已被读取 if (head.readIndex == LINK_CAPACITY) { //已被读取,则取下一个Link,下一个Link为空则说明WorkQueue中无对象 if (head.next == null) { return false; } head = head.next; //设置Head连接到新的Link,其中有一个隐藏的释放上一个Link对象数量操作 this.head.relink(head); } //Link中可用对象的起点下标 final int srcStart = head.readIndex; //Link中可用对象的终点下标 int srcEnd = head.get(); //Link中可用对象的数量 final int srcSize = srcEnd - srcStart; if (srcSize == 0) { return false; } //stack中对象的数量 final int dstSize = dst.size; //期望对象的数量 final int expectedCapacity = dstSize + srcSize; //如果期望对象的数量大于stack.elements的长度,则stack.elements扩容 if (expectedCapacity > dst.elements.length) { final int actualCapacity = dst.increaseCapacity(expectedCapacity); srcEnd = min(srcStart + actualCapacity - dstSize, srcEnd); } if (srcStart != srcEnd) { final DefaultHandle[] srcElems = head.elements; final DefaultHandle[] dstElems = dst.elements; int newDstSize = dstSize; for (int i = srcStart; i < srcEnd; i++) { DefaultHandle<?> element = srcElems[i]; //设置对象的recycleId=lastRecycledId if (element.recycleId == 0) { element.recycleId = element.lastRecycledId; } else if (element.recycleId != element.lastRecycledId) { throw new IllegalStateException("recycled already"); } srcElems[i] = null; //尝试丢弃这个对象 if (dst.dropHandle(element)) { // Drop the object. continue; } element.stack = dst; //将对象加入到stack的数组中 dstElems[newDstSize ++] = element; } if (srcEnd == LINK_CAPACITY && head.next != null) { //设置Head连接到新的Link,其中有一个隐藏的释放上一个Link对象数量操作 this.head.relink(head.next); } //设置head的readIndex head.readIndex = srcEnd; if (dst.size == newDstSize) { return false; } dst.size = newDstSize; return true; } else { // The destination stack is full already. return false; } } void relink(Link link) { reclaimSpace(LINK_CAPACITY); this.link = link; } private void reclaimSpace(int space) { availableSharedCapacity.addAndGet(space); } //stack.elements扩容 int increaseCapacity(int expectedCapacity) { int newCapacity = elements.length; int maxCapacity = this.maxCapacity; do { newCapacity <<= 1; } while (newCapacity < expectedCapacity && newCapacity < maxCapacity); newCapacity = min(newCapacity, maxCapacity); if (newCapacity != elements.length) { elements = Arrays.copyOf(elements, newCapacity); } return newCapacity; }