AQS source code analysis --jdk1.8

JDK1.8

ArrayList source code analysis --jdk1.8
LinkedList source code analysis --jdk1.8
HashMap source code analysis --jdk1.8
AQS source code analysis --jdk1.8

AbstractQueuedSynchronizer Overview

  1. AQS is based on a FIFO queue, the lock can be used to construct the base frame or other synchronization devices.
  2. AQS provides a doubly linked list.
  3. AQS into shared mode and exclusive mode.
  4.AQS volatile memory based on the visibility and CAS operations implemented atoms communication operation between threads.

AbstractQueuedSynchronizer data structure

  The data structure is the essence of a collection of lies, data structures often limit the role and focus of the collection, understand the various data structures we analyze the source code is the only way.
  AQS data structure follows: doubly linked list
  AQS source code analysis --jdk1.8
  AQS achieve control access to shared resources base:
     1.state field, i.e., the synchronization status field. Access to a shared resource control
     2.CLH queue, FIFO queue, storing the failure of competition thread. CLH is usually a queue spin queue, AQS in a blocking manner
     using CLH queue:
AQS source code analysis --jdk1.8

CLH Literacy

Spin lock
before learning about the spin lock mutex first look
mutex
thread mutex acquisition time, if we find the lock had been occupied by other threads, the thread will awaken to sleep, then at the right time (for example, wake) in acquiring the lock.
Spinlock
then spin lock by definition is "spin." After that is when a thread attempts to acquire the lock fails, the thread does not suspend or hibernate, but has been released whether other threads at the cycle lock.
The difference between
a mutex is the beginning of the cost is greater than the spin lock. Critical Area in size will not have time to lock mutex cost impact, while the spin lock loop detection is dead, locked the whole consumption cpu, although lower than the initial cost of a mutex, but with the lock hold time , locking overhead is linear growth.
For situations where a
mutex for the critical section lock holding a long time operation, these situations such as the following may be considered

There IO operations critical area
critical area code complexity or large circulation
critical region is very competitive
single-core processor
spin lock is mainly used in the critical region lock hold time is very short and resources are not under stressful circumstances CPU. May cause a deadlock when recursive call.
Thread (node) Queue
After understanding spinlock, when learning of ReentrantLock, a thread while waiting for the lock may be encapsulated into a node Node, and then added to a queue before detecting whether a node is head node, and attempts acquiring the lock, if successful returns acquires the lock, otherwise blocked. Until the release of a node lock and awaken it. It would appear that nothing seems linked with the spin. This is because the inside of the AQS CLH CLH modification queue is a queue of lock. Let's look at the queue lock CLH
CLH queue lock
CLH (Craig, Landin, and Hagersten locks): is a spin lock, to ensure no hunger, providing fairness first-come, first-served basis.
CLH is also a lock based on the list of scalable, high-performance, fair spin locks, apply spin thread only on a local variable, it continuously polls the state of the precursor, if we find the precursor to release the lock on the end of a spin. http://www.2cto.com/kf/201412/363574.html this article a more detailed illustration .
AQS CLH queue in
the understanding of the spin lock and CLH queue lock, CLH queue in learning AQS is relatively simple. AQS in CLH CLH queue queue mainly on changes in the lock in two places
1. The node structure changes made. CLH queue node comprises a lock locked Boolean field. If you want to acquire a lock, it will be this locked set to true. And then kept in rotation predecessor node locked whether to release the lock (this process we are called spin). The AQS CLH queue structure into the head node, tail node. And it has a reference to the next node before a node.
2. On the mechanism waiting to acquire the lock into a waiting blocked by the spin.
MCS
MSC and CLH biggest difference list is not displayed or implicit, but different spin thread rules: CLH is the first spin-wait on becoming locked domain node, and the MSC is in its own
node locked spin-wait on the domain. Because of this, it addresses the CLH get locked too far domain state memory problems NUMA system architecture.

AbstractQueuedSynchronizer source code analysis

/*
  * 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架
 * 双向链表
 */
public abstract class AbstractQueuedSynchronizer
    extends AbstractOwnableSynchronizer
    implements java.io.Serializable {

    /**
     * 无参构造方法
     */
    protected AbstractQueuedSynchronizer() { }

    /**
     * <pre>
     *      +------+  prev +-----+       +-----+
     * head |      | <---- |     | <---- |     |  tail
     *      +------+       +-----+       +-----+
     * </pre>
     */
    static final class Node {
        /** Marker to indicate a node is waiting in shared mode  模式,分为共享与独占 共享模式 */
        static final Node SHARED = new Node();
        /** Marker to indicate a node is waiting in exclusive mode 独占模式 */
        static final Node EXCLUSIVE = null;

        /** waitStatus value to indicate thread has cancelled
         * 结点状态 节点watiStatus的值
         * CANCELLED,值为1,终态,该节点被取消由于超时或中断
         * SIGNAL,值为-1,表示当前节点的后继节点包含的线程需要运行,也就是unpark,所以当前节点release或cancels时,必须unpark它的后继节点
         * CONDITION,值为-2,表示当前节点在等待condition,也就是在condition队列中 该节点处于条件队列中,将不会被用于sync queue,直到节点状态被设置为0
         * PROPAGATE,值为-3,表示当前场景下后续的acquireShared能够得以执行releaseShared应该被传播到其他节点
         * 值为0,表示当前节点在sync队列中,等待着获取锁
         * */
        static final int CANCELLED =  1;
        /** waitStatus value to indicate successor's thread needs unparking */
        static final int SIGNAL    = -1;
        /** waitStatus value to indicate thread is waiting on condition */
        static final int CONDITION = -2;
        /**
         * waitStatus value to indicate the next acquireShared should
         * unconditionally propagate
         */
        static final int PROPAGATE = -3;

        /**
         * Status field, taking on only the values:
         *   SIGNAL:     The successor of this node is (or will soon be)
         *               blocked (via park), so the current node must
         *               unpark its successor when it releases or
         *               cancels. To avoid races, acquire methods must
         *               first indicate they need a signal,
         *               then retry the atomic acquire, and then,
         *               on failure, block.
         *   CANCELLED:  This node is cancelled due to timeout or interrupt.
         *               Nodes never leave this state. In particular,
         *               a thread with cancelled node never again blocks.
         *   CONDITION:  This node is currently on a condition queue.
         *               It will not be used as a sync queue node
         *               until transferred, at which time the status
         *               will be set to 0. (Use of this value here has
         *               nothing to do with the other uses of the
         *               field, but simplifies mechanics.)
         *   PROPAGATE:  A releaseShared should be propagated to other
         *               nodes. This is set (for head node only) in
         *               doReleaseShared to ensure propagation
         *               continues, even if other operations have
         *               since intervened.
         *   0:          None of the above
         * 结点状态
         */
        volatile int waitStatus;

        /**
         * 前驱结点
         */
        volatile Node prev;

        /**
         * 后继结点
         */
        volatile Node next;

        /**
         * 结点所对应的线程
         */
        volatile Thread thread;

        /**
         * 下一个等待者
         */
        Node nextWaiter;

        /**
         * 结点是否在共享模式下等待
         */
        final boolean isShared() {
            return nextWaiter == SHARED;
        }

        /**
         * 获取前驱结点,若前驱结点为空,抛出异常
         */
        final Node predecessor() throws NullPointerException {
            // 保存前驱结点
            Node p = prev;
            if (p == null) // 前驱结点为空,抛出异常
                throw new NullPointerException();
            else // 前驱结点不为空,返回
                return p;
        }

        // 无参构造函数
        Node() {    // Used to establish initial head or SHARED marker
        }
        // 构造函数
        Node(Thread thread, Node mode) {     // Used by addWaiter
            this.nextWaiter = mode;
            this.thread = thread;
        }
        // 构造函数
        Node(Thread thread, int waitStatus) { // Used by Condition
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }

    /**
     * CLH队列中头结点
     */
    private transient volatile Node head;

    /**
     * CLH队列中尾结点
     */
    private transient volatile Node tail;

    /**
     * 同步状态
     * 多线程同步获取资源成功,则state字段会自增;若有线程释放资源,则state字段自减。
     * 信号量  记录该线程持有锁的次数。 该线程每次释放所 信号量 -1。 信号量为零 代表 锁被真正释放
     */
    private volatile int state;

    /**
     * @return current state value
     */
    protected final int getState() {
        return state;
    }

    /**
     * @param newState the new state value
     */
    protected final void setState(int newState) {
        state = newState;
    }

    /**
     * 使用unsafe的cas比较并且交换,保证原子性
     */
    protected final boolean compareAndSetState(int expect, int update) {
        // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

AbstractQueuedSynchronizer inherit and implement analysis

AQS source code analysis --jdk1.8

   The extends AbstractOwnableSynchronizer AbstractQueuedSynchronizer
   1. AbstractOwnableSynchronizer is an abstract class that implements Serializable interface defines the exclusive mode, set and retrieve information in the thread Thread exclusive mode.
   2.ArrayList implements List <E>, RandomAccess, Cloneable , Serializable Interface
     1) List <E> interface inherits from ArrayList since AbstractList abstract class, and has achieved AbstractList List interface, ArrayList class why they would go to achieve the List interface it? We look down with a question:

public class Demo1 extends ArrayList {
    public static void main(String[] args) {
                //返回[]
        System.out.println(Arrays.toString(Demo1.class.getInterfaces()));
    }
public class Demo2 implements Serializable {
    public static void main(String[] args) {
                //返回[interface java.io.Serializable]
        System.out.println(Arrays.toString(Demo2.class.getInterfaces()));
    }
public class Test{
    public static void main(String[] args) {
                Serializable c1 = new Demo1();//未显示实现接口
                Serializable c2 = new Demo2();//显示实现接口
                Serializable proxy2 = createProxy(c2);
                proxy2.foo();
                Serializable proxy1 = createProxy(c1);
                proxy1.foo();
 }

private static <T> T createProxy(final T obj) {
        final InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                return method.invoke(obj, args);
            }
        };
                //实现接口代理,Demo1报错,Demo2成功
                //java.lang.ClassCastException: $Proxy1 cannot be cast to
                //example.Test$Serializable
        return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
                .getClass().getInterfaces(), handler);
    }

In this way we can see this design makes sense, therefore, this is not a mistake, it is likely the author Josh Bloch To facilitate agent and well-designed.
Reference to: develop a collection of Josh says
     2) RandomAccess interface, which is a marker interface, this marker interface is generally used to implement List, to indicate that they support fast (generally constant time) random access, the main purpose of this interface is allow general algorithm to change their behavior in order to be applied to a random or sequential access lists provide good performance achieved if the interface using common for loops to traverse, higher performance, and does not implement this interface, use iterator iterate , so that a higher performance, e.g. linkedList. So the mark of us just to let us know what kind of a way to get better data performance
     3) Cloneable interface, you can use Object.Clone () method.
     4) Serializable interfaces, serial interfaces, indicating that the class can be serialized, what is serialized? Simply put, into a stream of bytes that can be transmitted from the class deserialized, it is to become the original byte stream from the class

ArrayList core analysis methods

1. add method (4 types overload implemented) - increasing    

AQS source code analysis --jdk1.8

     1) add (E); // default to the element directly to the end

/**
 * 新增元素
 */
public boolean add(E e) {
    //赋值初始长度  或者扩容,新增元素,当前实际size+1的长度
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //添加元素
        elementData[size++] = e;
        return true;
}
    /**
     * 确保elemenData数组有合适的大小
     * 如果元素为空,则复制长度默认为10 或者更大
    * @author jiaxiaoxian
    * @date 2019年2月12日 
     */
    private void ensureCapacityInternal(int minCapacity) {
            if (elementData == EMPTY_ELEMENTDATA) {//如果数组为空,则从size+1的值和默认值10中取最大的
                    minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
            }
            ensureExplicitCapacity(minCapacity);
    }
/**
* 确保elemenData数组有合适的大小
* @author jiaxiaoxian
* @date 2019年2月12日 
* 如果长度大于元素长度则扩容
 */
private void ensureExplicitCapacity(int minCapacity) {
    //记录修改次数,迭代中不一致会触发fail-fast机制,因此在遍历中删除元素的正确做法应该是使用Iterator.remove()
    modCount++;
    if (minCapacity - elementData.length > 0)
        grow(minCapacity); //扩容
}
/**
 * 扩容
 */
private void grow(int minCapacity) {
    int oldCapacity = elementData.length; // 旧容量
    int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量为旧容量的1.5倍
    if (newCapacity - minCapacity < 0) // 新容量小于参数指定容量,修改新容量
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)  // 新容量大于最大容量
        newCapacity = hugeCapacity(minCapacity); // 指定新容量
    // minCapacity is usually close to size, so this is a win:  拷贝扩容
    elementData = Arrays.copyOf(elementData, newCapacity);
}
    //如果小于0 就报错,如果大于最大值 则取最大值
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

     2) add (int index, E element); // to the specified index, the additive element

/**
 * 给指定下标,添加元素
 */
public void add(int index, E element) {
    //判断下标是否越界
    rangeCheckForAdd(index);
    //赋值初始长度  或者扩容
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    //将源数组中从index位置开始后的size-index个元素统一后移一位
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    //赋值
    elementData[index] = element;
    size++;
}
/**
 * 判断下标是否越界
 */
private void rangeCheckForAdd(int index) {
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
 *     src:源数组
 *   srcPos:源数组要复制的起始位置
 *   dest:目的数组
 *   destPos:目的数组放置的起始位置
 *   length:复制的长度
 *   注意:src 和 dest都必须是同类型或者可以进行转换类型的数组
 */
public static native void arraycopy(Object src,  int  srcPos,
                                    Object dest, int destPos,
                                    int length);

     3) addAll (Collection c) <extends E?>; // add an element of type Collection

/**
 * 按照指定collection的迭代器所返回的元素顺序,将该collection中的所有元素添加到此列表的尾部
 */
public boolean addAll(Collection<? extends E> c) {
    Object[] a = c.toArray();
    int numNew = a.length;
    ensureCapacityInternal(size + numNew);  // Increments modCount
    //将数组a[0,...,numNew-1]复制到数组elementData[size,...,size+numNew-1]
    System.arraycopy(a, 0, elementData, size, numNew);
    size += numNew;
    return numNew != 0;
}

     4) addAll (int index, Collection c) <extends E?>; // the specified location, the type of element added Collection

/**
 * 从指定的位置开始,将指定collection中的所有元素插入到此列表中,新元素的顺序为指定collection的迭代器所返回的元素顺序
 */
public boolean addAll(int index, Collection<? extends E> c) {
    //判断下标是否越界
    rangeCheckForAdd(index);
    Object[] a = c.toArray();
    int numNew = a.length;
    ensureCapacityInternal(size + numNew);  // Increments modCount
    int numMoved = size - index;
    //先将数组elementData[index,...,index+numMoved-1]复制到elementData[index+numMoved,...,index+2*numMoved-1]
    //即,将源数组中从index位置开始的后numMoved个元素统一后移numNew位
    if (numMoved > 0)
        System.arraycopy(elementData, index, elementData, index + numNew,
                         numMoved);
    System.arraycopy(a, 0, elementData, index, numNew);
    size += numNew;
    return numNew != 0;
}

Summary:
   Under normal circumstances would be 1.5 times the expansion in special cases (new extension has reached the maximum array size) only takes a maximum value.
   

2.remove method (4 types overload implemented) - deleted

AQS source code analysis --jdk1.8

     1) remove (int index); // delete the element according to the specified index     

/**
 * 根据指定下标 删除元素
 */
public E remove(int index) {
    //判断索引是否越界
    rangeCheck(index);
    modCount++;
    //获取旧元素
    E oldValue = elementData(index);
    //将数组elementData中index位置之后的所有元素向前移一位
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    //将原数组最后一个位置置为null,由GC清理
    elementData[--size] = null; // clear to let GC do its work
    return oldValue;
}       

     2) remove (Object o); // delete elements in accordance with the specified element 

 /**
 * 移除ArrayList中首次出现的指定元素(如果存在),ArrayList中允许存放重复的元素
 */
public boolean remove(Object o) {
    // 由于ArrayList中允许存放null,因此下面通过两种情况来分别处理。
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                //私有的移除方法,跳过index参数的边界检查以及不返回任何值
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}   
/*
 * 根据下标快速删除元素
 */
private void fastRemove(int index) {
    modCount++;
    //将数组elementData中index位置之后的所有元素向前移一位
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work
}
 /**
 * 清空ArrayList,将全部的元素设为null,等待垃圾回收将这个给回收掉,所以叫clear
 */
public void clear() {
    modCount++;
    // clear to let GC do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;
    size = 0;
}

     3) removeAll (Collection c) <?>; // delete contained in the specified container c of all the elements 

/**
 * 删除ArrayList中包含在指定容器c中的所有元素
 */
public boolean removeAll(Collection<?> c) {
    //检查指定的对象c是否为空
    Objects.requireNonNull(c);
    return batchRemove(c, false);
}
 /**
 * 删除全部
* @author jiaxiaoxian
* @date 2019年2月12日 
 */
private boolean batchRemove(Collection<?> c, boolean complement) {
    final Object[] elementData = this.elementData;
    int r = 0, w = 0; //读写双指针
    boolean modified = false;
    try {
        for (; r < size; r++)
            if (c.contains(elementData[r]) == complement) //判断指定容器c中是否含有elementData[r]元素
                elementData[w++] = elementData[r];
    } finally {
        // Preserve behavioral compatibility with AbstractCollection,
        // even if c.contains() throws.
        if (r != size) {
            System.arraycopy(elementData, r,
                             elementData, w,
                             size - r);
            w += size - r;
        }
        if (w != size) {
            // clear to let GC do its work
            for (int i = w; i < size; i++)
                elementData[i] = null;
            modCount += size - w;
            size = w;
            modified = true;
        }
    }
    return modified;
}

     4) removeIf (Predicate filter) <super E?>; // filter element (deletion) set according to certain rules 

/**
 * 按照一定规则过滤(删除)集合中的元素
 * 如:idList.removeIf(id -> id == nul);
    *   去掉 List idList 集合中id 为 null 的
 * @param filter
 * @return
 */
@Override
public boolean removeIf(Predicate<? super E> filter) {
    Objects.requireNonNull(filter);
    // figure out which elements are to be removed
    // any exception thrown from the filter predicate at this stage
    // will leave the collection unmodified
    int removeCount = 0;
    final BitSet removeSet = new BitSet(size);
    final int expectedModCount = modCount;
    final int size = this.size;
    for (int i=0; modCount == expectedModCount && i < size; i++) {
        @SuppressWarnings("unchecked")
        final E element = (E) elementData[i];
        if (filter.test(element)) {
            removeSet.set(i);
            removeCount++;
        }
    }
    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }

    // shift surviving elements left over the spaces left by removed elements
    final boolean anyToRemove = removeCount > 0;
    if (anyToRemove) {
        final int newSize = size - removeCount;
        for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
            i = removeSet.nextClearBit(i);
            elementData[j] = elementData[i];
        }
        for (int k=newSize; k < size; k++) {
            elementData[k] = null;  // Let gc do its work
        }
        this.size = newSize;
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }

    return anyToRemove;
}

Summary:
   Remove the specified function of the user removes the target element, will at this time to the end of the specified index of the array element is moved forward by one unit, and the last element of the array will be set to null, then this is to facilitate the entire array is not when used, will be GC, it can be used as a small trick.

3.set method - change

/**
 * 覆盖指定下标元素
 */
public E set(int index, E element) {
    //判断索引是否越界
    rangeCheck(index);
    //获取旧元素
    E oldValue = elementData(index);
    //覆盖为新元素
    elementData[index] = element;
    //返回旧元素
    return oldValue;
}
/**
 * 判断下标是否越界
 */
private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

4.get method - check

 /**
 * 返回指定索引的值
 */
public E get(int index) {
    //判断索引是否越界
    rangeCheck(index);
    return elementData(index);
}
/**
* @author jiaxiaoxian
* @date 2019年2月12日 
* 返回下标元素的 值
 */
@SuppressWarnings("unchecked")
E elementData(int index) {
    return (E) elementData[index];
}

5.indexOf method - Find subscript

/**
 * 查找下标, 如果为null,直接和null比较,返回下标
 */
public int indexOf(Object o) {
    if (o == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}
/**
 * 查找最后出现的下标,从大往下循环查找
 */
public int lastIndexOf(Object o) {
    if (o == null) {
        for (int i = size-1; i >= 0; i--)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = size-1; i >= 0; i--)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}

Method 6.clone - Cloning

 /**
 * 复制,返回此ArrayList 的浅拷贝
 */
public Object clone() {
    try {
        ArrayList<?> v = (ArrayList<?>) super.clone();
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

7.trimToSize - Remove redundant capacity

/**
 * 判断数据实际容量大小,删除自动增长后冗余的容量
 * 该方法用于回收多余的内存。也就是说一旦我们确定集合不在添加多余的元素之后,调用 trimToSize() 方法会将实现集合的数组大小刚好调整为集合元素的大小。
 *   注意:该方法会花时间来复制数组元素,所以应该在确定不会添加元素之后在调用
 */
public void trimToSize() {
    modCount++;
    if (size < elementData.length) {
        elementData = Arrays.copyOf(elementData, size);
    }
}

8.Itr inner classes - similar Iterator, can help us to traverse List, CRUD etc.

/**
 * 实例化一个Itr对象,并返回
 */
public Iterator<E> iterator() {
    return new Itr();
}

/**
 * 内部类,类似Iterator,可以帮我们对List进行遍历,增删改查等
 */
private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return 下一个元素
    int lastRet = -1; // index of last element returned; -1 if no such 当前元素
    int expectedModCount = modCount; //modCount,就是为了判断是否有多个线程访问修改

    public boolean hasNext() {
        return cursor != size;
    }

    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }

    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void forEachRemaining(Consumer<? super E> consumer) {
        Objects.requireNonNull(consumer);
        final int size = ArrayList.this.size;
        int i = cursor;
        if (i >= size) {
            return;
        }
        final Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length) {
            throw new ConcurrentModificationException();
        }
        while (i != size && modCount == expectedModCount) {
            consumer.accept((E) elementData[i++]);
        }
        // update once at end of iteration to reduce heap write traffic
        cursor = i;
        lastRet = i - 1;
        checkForComodification();
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}   

9.ListItr inner class - class inherits internal Itr, increasing the forward traversal is still based on this, adding elements, change the element content and other functions

/**
 * 这个类继承了内部类Itr
 * 除了拥有上一个类的功能,还增加了向前遍历,增加元素,更改元素内容等功能
 */
private class ListItr extends Itr implements ListIterator<E> {
    ListItr(int index) {
        super();
        cursor = index;
    }

    public boolean hasPrevious() {
        return cursor != 0;
    }

    public int nextIndex() {
        return cursor;
    }

    public int previousIndex() {
        return cursor - 1;
    }

    @SuppressWarnings("unchecked")
    public E previous() {
        checkForComodification();
        int i = cursor - 1;
        if (i < 0)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i;
        return (E) elementData[lastRet = i];
    }

    public void set(E e) {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.set(lastRet, e);
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    public void add(E e) {
        checkForComodification();

        try {
            int i = cursor;
            ArrayList.this.add(i, e);
            cursor = i + 1;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
}   

10.SubList inner classes - ArrayList built based on a subset of the class

/**
 * 虽然这个类很长,其实里面的大部分方法调用都是ArrayList中的
 * ListIterator在这个类中采用匿名内部类做了一点更改,不过也很类似
 * 毕竟这个类就是根据ArrayList建一个子集类,就不赘述了
 */
private class SubList extends AbstractList<E> implements RandomAccess {
    private final AbstractList<E> parent;
    private final int parentOffset;
    private final int offset;
    int size;

    SubList(AbstractList<E> parent,
            int offset, int fromIndex, int toIndex) {
        this.parent = parent;
        this.parentOffset = fromIndex;
        this.offset = offset + fromIndex;
        this.size = toIndex - fromIndex;
        this.modCount = ArrayList.this.modCount;
    }

    public E set(int index, E e) {
         // 检验索引是否合法
        rangeCheck(index);
        //实现fail-fast机制  (迭代中不允许操作增删改)
        checkForComodification();
        // 旧值
        E oldValue = ArrayList.this.elementData(offset + index);
        // 赋新值
        ArrayList.this.elementData[offset + index] = e;
        return oldValue;
    }

    public E get(int index) {
         // 检验索引是否合法
        rangeCheck(index);
        //实现fail-fast机制  (迭代中不允许操作增删改)
        checkForComodification();
        return ArrayList.this.elementData(offset + index);
    }

    public int size() {
        checkForComodification();
        return this.size;
    }

    public void add(int index, E e) {
        rangeCheckForAdd(index);
        checkForComodification();
        parent.add(parentOffset + index, e);
        this.modCount = parent.modCount;
        this.size++;
    }

    public E remove(int index) {
        rangeCheck(index);
        checkForComodification();
        E result = parent.remove(parentOffset + index);
        this.modCount = parent.modCount;
        this.size--;
        return result;
    }

    protected void removeRange(int fromIndex, int toIndex) {
        checkForComodification();
        parent.removeRange(parentOffset + fromIndex,
                           parentOffset + toIndex);
        this.modCount = parent.modCount;
        this.size -= toIndex - fromIndex;
    }

    public boolean addAll(Collection<? extends E> c) {
        return addAll(this.size, c);
    }

    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        int cSize = c.size();
        if (cSize==0)
            return false;

        checkForComodification();
        parent.addAll(parentOffset + index, c);
        this.modCount = parent.modCount;
        this.size += cSize;
        return true;
    }

    public Iterator<E> iterator() {
        return listIterator();
    }

    public ListIterator<E> listIterator(final int index) {
        checkForComodification();
        rangeCheckForAdd(index);
        final int offset = this.offset;

        return new ListIterator<E>() {
            int cursor = index;
            int lastRet = -1;
            int expectedModCount = ArrayList.this.modCount;

            public boolean hasNext() {
                return cursor != SubList.this.size;
            }

            @SuppressWarnings("unchecked")
            public E next() {
                checkForComodification();
                int i = cursor;
                if (i >= SubList.this.size)
                    throw new NoSuchElementException();
                Object[] elementData = ArrayList.this.elementData;
                if (offset + i >= elementData.length)
                    throw new ConcurrentModificationException();
                cursor = i + 1;
                return (E) elementData[offset + (lastRet = i)];
            }

            public boolean hasPrevious() {
                return cursor != 0;
            }

            @SuppressWarnings("unchecked")
            public E previous() {
                checkForComodification();
                int i = cursor - 1;
                if (i < 0)
                    throw new NoSuchElementException();
                Object[] elementData = ArrayList.this.elementData;
                if (offset + i >= elementData.length)
                    throw new ConcurrentModificationException();
                cursor = i;
                return (E) elementData[offset + (lastRet = i)];
            }

            @SuppressWarnings("unchecked")
            public void forEachRemaining(Consumer<? super E> consumer) {
                Objects.requireNonNull(consumer);
                final int size = SubList.this.size;
                int i = cursor;
                if (i >= size) {
                    return;
                }
                final Object[] elementData = ArrayList.this.elementData;
                if (offset + i >= elementData.length) {
                    throw new ConcurrentModificationException();
                }
                while (i != size && modCount == expectedModCount) {
                    consumer.accept((E) elementData[offset + (i++)]);
                }
                // update once at end of iteration to reduce heap write traffic
                lastRet = cursor = i;
                checkForComodification();
            }

            public int nextIndex() {
                return cursor;
            }

            public int previousIndex() {
                return cursor - 1;
            }

            public void remove() {
                if (lastRet < 0)
                    throw new IllegalStateException();
                checkForComodification();

                try {
                    SubList.this.remove(lastRet);
                    cursor = lastRet;
                    lastRet = -1;
                    expectedModCount = ArrayList.this.modCount;
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }

            public void set(E e) {
                if (lastRet < 0)
                    throw new IllegalStateException();
                checkForComodification();

                try {
                    ArrayList.this.set(offset + lastRet, e);
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }

            public void add(E e) {
                checkForComodification();

                try {
                    int i = cursor;
                    SubList.this.add(i, e);
                    cursor = i + 1;
                    lastRet = -1;
                    expectedModCount = ArrayList.this.modCount;
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }

            final void checkForComodification() {
                if (expectedModCount != ArrayList.this.modCount)
                    throw new ConcurrentModificationException();
            }
        };
    }

    public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList(this, offset, fromIndex, toIndex);
    }

    private void rangeCheck(int index) {
        if (index < 0 || index >= this.size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private void rangeCheckForAdd(int index) {
        if (index < 0 || index > this.size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+this.size;
    }

    /**
     * 实现fail-fast机制 
     * 线程不安全    迭代中不允许修改
    * @author jiaxiaoxian
    * @date 2019年2月12日 
     */
    private void checkForComodification() {
        if (ArrayList.this.modCount != this.modCount)
            throw new ConcurrentModificationException();
    }

    public Spliterator<E> spliterator() {
        checkForComodification();
        return new ArrayListSpliterator<E>(ArrayList.this, offset,
                                           offset + this.size, this.modCount);
    }
}

11.ArrayListSpliterator inner classes - Parallel iteration, based on an index of binary fission, lazy initialization Spliterator

/**
 * @since 1.8
 * 实例化一个ArrayListSpliterator对象,并返回
 */
@Override
public Spliterator<E> spliterator() {
    return new ArrayListSpliterator<>(this, 0, -1, 0);
}

/**
 * Index-based split-by-two, lazily initialized Spliterator
 * 并行迭代
 * 基于索引的二分裂,懒惰初始化的Spliterator
 * */
static final class ArrayListSpliterator<E> implements Spliterator<E> {

    private final ArrayList<E> list;
    private int index; // current index, modified on advance/split
    private int fence; // -1 until used; then one past last index
    private int expectedModCount; // initialized when fence set

    /** Create new spliterator covering the given  range */
    ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
                         int expectedModCount) {
        this.list = list; // OK if null unless traversed
        this.index = origin;
        this.fence = fence;
        this.expectedModCount = expectedModCount;
    }

    private int getFence() { // initialize fence to size on first use
        int hi; // (a specialized variant appears in method forEach)
        ArrayList<E> lst;
        if ((hi = fence) < 0) {
            if ((lst = list) == null)
                hi = fence = 0;
            else {
                expectedModCount = lst.modCount;
                hi = fence = lst.size;
            }
        }
        return hi;
    }

    public ArrayListSpliterator<E> trySplit() {
        int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
        return (lo >= mid) ? null : // divide range in half unless too small
            new ArrayListSpliterator<E>(list, lo, index = mid,
                                        expectedModCount);
    }

    public boolean tryAdvance(Consumer<? super E> action) {
        if (action == null)
            throw new NullPointerException();
        int hi = getFence(), i = index;
        if (i < hi) {
            index = i + 1;
            @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
            action.accept(e);
            if (list.modCount != expectedModCount)
                throw new ConcurrentModificationException();
            return true;
        }
        return false;
    }

    public void forEachRemaining(Consumer<? super E> action) {
        int i, hi, mc; // hoist accesses and checks from loop
        ArrayList<E> lst; Object[] a;
        if (action == null)
            throw new NullPointerException();
        if ((lst = list) != null && (a = lst.elementData) != null) {
            if ((hi = fence) < 0) {
                mc = lst.modCount;
                hi = lst.size;
            }
            else
                mc = expectedModCount;
            if ((i = index) >= 0 && (index = hi) <= a.length) {
                for (; i < hi; ++i) {
                    @SuppressWarnings("unchecked") E e = (E) a[i];
                    action.accept(e);
                }
                if (lst.modCount == mc)
                    return;
            }
        }
        throw new ConcurrentModificationException();
    }

    public long estimateSize() {
        return (long) (getFence() - index);
    }

    public int characteristics() {
        return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
    }
}

ArrayList summary

1)arrayList可以存放null,本质是Object[]类型的数组。
2)arrayList区别于数组的地方在于能够自动扩展大小,其中关键的方法就是gorw()方法。
3)arrayList由于本质是数组,所以它在数据的查询方面会很快,而在插入删除这些方面,性能下降很多,有移动很多数据才能达到应有的效果,而LinkedList则相反。
4)arrayList实现了RandomAccess,所以在遍历它的时候推荐使用for循环。
5)初始化数组时推荐给初始长度,反复扩容会增加时耗,影响性能效率。

Guess you like

Origin blog.51cto.com/hackerxian/2427864