您的位置 首页 java

彻底搞懂JAVA的ArrayList,Set,Queue

(一)ArrayList

  • ① 介绍

List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。

  • ② 内部的存储方式

ArrayList默认有一个空的数组, 数据的顺序插入,如果当前的数组长度不够存储的时候,进行扩容处理,直接去创建一个新的数组,创建完成之后,把数组进行拷贝,本身是线程非安全的,不要一边遍历,一边删除代码。扩容的时候存在i++,之前也说过i++的情况下很容易存在高并发问题。

(二)CopyOnWriteArrayList

  • ① 介绍

List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。

  • ② 内部的存储方式

内部持有一个ReentrantLock lock = new ReentrantLock();底层是用volatile transient声明的数组 array
读写分离,写时复制出一个新的数组,完成插入。修改或者移除操作后将新数组赋值给array

(三)ArrayList 和 CopyOnWriteArrayList

CopyOnWriteArrayList容器即写时复制的容器和ArrayList比较,优点是并发安全,缺点有两个

  1. 多了内存占用,写数据是copy一份完成的数据,单独进行操作,占用两份内存。
  2. 数据一致性:数据写完之后,其他线程不一定是马上读取到最新内容。

(四)Set

  • ① 介绍

无序(没有下标) 集合中的元素不重复。

  • ② Set集合

  • ③ HashSet

因为是基于HashMap的,只要保证key不重复,其实内部就不会重复。

  • ④ CopyOnWriteArraySet

CopyOnWriteArrayList中允许有重复的元素;但是,CopyOnWriteArraySet是一个集合,所以它不能有重复集合,因此,CopyOnWriteArrayList额外提供了addIfAbsent()和addAllAbsent()这两个添加元素的API,通过这些API来添加元素时,只有当元素不存在时才执行添加操作!

  • ⑤ ConcurrentSkipListSet

所有操作都是无阻塞的,所有操作都可以并行,包括写,实现了ConcurrentMap接口,直接支持一些原子复合操作(与ConcurrentHashMap类似),可排序(与TreeMap一样),默认按键自然有序,可以传递比较器自定义排序,实现了SortedMap和NavigableMap接口。

(五)Queue

  • ① 介绍

基本上,一个队列就是一个先入先出(FIFO)的数据结构。

  • ② 阻塞和非阻塞
  1. 我去买一本书,立即买到了,或者没有就走了,这就是非阻塞;(编程中设置IO成非阻塞,返回后再去检查描述符,或者等待通知,然后再去读取。相当于老板告诉我可以先忙点别的,过一会再来问问,或者老板通知我。但期间这个窗口(文件描述符)别人是用不了的)(“立即买到了”在IO中也需要等待,不能算非阻塞IO)
  2. 如果恰好书店没有,我就等一直等到书店有了这本书买到了才走,这就是阻塞;而排在我后面的人呢只有我买到了书后才能再买书了。
  3. 如果书店恰好没有,我就告诉书店老板,书来了告诉我一声让我来取或者直接送到我家,然后我就走了,去做别的事了,这就是异步。这时候如果很多人来买书,都是老板登记一下完事。 (从IO角度来说,“告诉我来取”,这个近似于信号驱动IO,不能算异步IO。必须书送到我家才算是异步,如果不送到我家,我想看这本书之前,终究还是需要我跑一趟)
  4. 前面两种情况,非阻塞和阻塞都可以称为同步。
  • ③ 常用方法

  • ④ ArrayBlockingQueue

ArrayBlockingQueue是采用数组实现的有界阻塞线程安全队列。如果向已满的队列继续塞入元素,将导致当前的线程阻塞。如果向空队列获取元素,那么将导致当前线程阻塞。

前面三秒是没有数据的,等数据存储完毕后才可以读取。用了6个线程来完成。队列对于 线程池 ,连接池都会有队列的使用,存放一些对象和数据。
存放:里面设置了lock,拿到一把锁,然后进行入队列,数量++, 索引 自行维护putIndex。
移除:数量–,找到对应的节点,lock设置了一把锁。索引自行维护takeIndex(记录下一个要获取的)。

  • ⑤ DelayQueue

DelayQueue是一个无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的Delayed 元素。
DelayQueue是一个用来延时处理的队列,所谓延时处理就是说可以为队列中元素设定一个过期时间,相关的操作受到这个设定时间的控制。

延迟的排序是根据谁快,谁的位置最靠前。

  • ⑥ LinkedBlockingQueue

存放数据的方式: 链表 的形式。
入队列用了Atomic的形式,原子性。
LinkedBlockingQueue 和 ConcurrentBlockingQueue 两个的区别是 LinkedBlockingQueue 是通过lock加锁的方式,ConcurrentBlockingQueue 是通过cas的方式。

  • ⑦ PriorityBlockingQueue

  • ⑧ PriorityQueueDemo

一个带优先级的 队列,而不是先进先出队列。
元素按优先级顺序被移除,该队列也没有上限, 没有容量限制的,自动扩容。
虽然此队列逻辑上是无界的,但是由于资源被耗尽,所以试图执行添加操作可能会导致 OutOfMemoryError), 但是如果队列为空, 那么取元素的操作take就会阻塞,所以它的检索操作take是受阻的。另外, 入该队列中的元素要具有比较能力
new Comparator<MessageObject>() 比较器

  • ⑨ SynchronousQueue

SynchronousQueue 就是不存队列的,里面是不存数据的。源码里面不存在存储单位。
这个方法就是等待,

PS:ArrayList链表,Set不重复链表,Queue队列,90%的可能都是使用现有JDK已经提供的方法,很少自己去实现这些功能。针对这几个源码可以好好的看下,尝试画下图,其实花不了多少时间的,JVM,JDK都是很基础的东西,翻过这座山就比别人强,一定要手把手的摸过,手把手的爬过去的,好记性不如烂笔头,一定要实战才能出真知,磨刀不误砍柴工,就是从哪个阶段过来的,理解都渴望学习新框架,新技术的心情,相信厚积薄发吧。

文章来源:智云一二三科技

文章标题:彻底搞懂JAVA的ArrayList,Set,Queue

文章地址:https://www.zhihuclub.com/191312.shtml

关于作者: 智云科技

热门文章

网站地图