java 容器

java 容器

数组

数组的扩容问题

ArrayList 的默认初始化容量为0,首次添加元素时,创建容量为(10 || 添加集合大小) ,以后每次扩容的话,为当前容量的1.5倍

public ArrayList() {
    /*
    初始化容量大小为0
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    */
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

 private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //容量取 10 或 minCapacity
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
    //扩容机制,向右移动1位 即1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        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);
    }



并发访问数组问题

当我们遍历的同时修改数组元素的时候我们会面临并发修改数组的问题,比如我们使用 iterator 迭代器进行数组的遍历,同时使用 arrayList.remove进行元素的删除,则会导致并发修改异常。

导致并发修改的问题相当于文件快照版本号的对比。

private class Itr implements Iterator<E> {
		//在创建迭代器的时候会记录快照的版本号
        int expectedModCount = modCount;

        Itr() {}
}
//每次在next 或者 remove 的时候会进行快照的检查如果快照版本已经被修改则会导致 并发修改异常
public E next() {
    //检查版本号是否匹配
    checkForComodification();
}
final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}


解决方案:

使用 iterator 提供的 remove 方法,或使用 for() 从尾部进行迭代并删除(避免头部操作的话导致的数组越界异常

HashMap

ConcurrentHashMap

CopyOnWriteArrayList

从两个方面入手分析,分别从 add 方法,代表 操作数组的所有写的方法,二是从iterator方法,代表所有读的方法

 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();
        }
    }
public Iterator<E> iterator() {
    //创建iterator 并将数组的引用传递给iterator ,由于没有加锁,现在我们知道,我们读取的数据,并不一定是实时可见的
    return new COWIterator<E>(getArray(), 0);
}

Queue

queue 的继承关系图

queue 接口提供的方法

Summary of Queue methods
Throws exceptionReturns special value
Insert Queue#add add(e) Queue#offer offer(e)
Remove Queue#remove remove() Queue#poll poll()
Examine 查看但不进行元素删除的操作 Queue#element element() Queue#peek peek()

Deque 接口提供的方法

Summary of Deque methods
First Element (Head) Last Element (Tail)
Throws exceptionSpecial valueThrows exceptionSpecial value
Insert Deque#addFirst addFirst(e) Deque#offerFirst offerFirst(e) Deque#addLast addLast(e) Deque#offerLast offerLast(e)
Remove Deque#removeFirst removeFirst() Deque#pollFirst pollFirst() Deque#removeLast removeLast() Deque#pollLast pollLast()
Examine Deque#getFirst getFirst() Deque#peekFirst peekFirst() Deque#getLast getLast() Deque#peekLast peekLast()

BlockingQueue接口提供的方法

Summary of BlockingQueue methods
Throws exceptionSpecial valueBlocksTimes out
Insert #add add(e) #offer offer(e) #put put(e) #offer(Object, long, TimeUnit) offer(e, time, unit)
Remove #remove remove() #poll poll() #take take() #poll(long, TimeUnit) poll(time, unit)
Examine #element element() #peek peek()not applicablenot applicable

其他综合说明

ConcurrentLinkedQueue 是无限容量,LinkedBlockingQueue可以指定容量,在不指定容量时,默认容量为Integer 的最大值, ArrayBlockingQueue 需要指定容量,SynchronousQueue 容量为1,进行同步交换。

关于线程池还有一点说明,线程池中将command 从 blockingQueue 中取出时,并非用的 put 方法,而是使用的offer() 非阻塞方法。

//固定大小线程池使用的是  容量为interger 的最大值的  queue
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
}
//单线程池使用的是  容量为interger 的最大值的  queue
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}
// 缓存线程池使用的是 同步的队列
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
}
//使用的是DelayedWorkQueue
public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

学习资料推广

我已经将springamqp 源码解析录制为视频上传到bibi,分为六个章节详细介绍了各个模块的具体内容

https://www.bilibili.com/video/BV1hN411Z7fn?share_source=copy_web

感兴趣的小伙伴可以看看
学习一下
录制不易,记得三联哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值