java并发容器

CopyOnWriteArrayList
  并发容器,底层数组,读写分离,适合读大于写的操作,迭代器和加强for循环不会ConcurrentModificationException异常
  修改/添加/删除时复制(浅复制)新的数组,使用新的数组,查询和迭代时使用老的数组(使用老的for循环会出现异常),迭代时和修改/添加/删除时使用不同的数据源
  修改/添加/删除时加锁,读不加锁
  CopyOnWriteArraySet
类似于CopyOnWriteArrayList,底层使用CopyOnWriteArrayList
不允许重复
CopyOnWrite容器有很多优点,但是同时也存在两个问题,即内存占用问题和数据一致性问题。
1.保持最终一致性 2.在修改时复制了新数组,所以内存中存在多个数组

concurrenthashmap
底层数组+hash结构
原理锁分段,用new object[16]中每个元素作为一个锁,然后用synchronized(object[hash(key)%16])进行同步
ConcurrentMap接口中增加了一些常见的复合操作的支持。对ConcurrentHashMap进行迭代不会抛出异常(弱一致性)。
size,isEnptry这些方法的语意被减弱了以反映容器的并发特性,还包括(get、put、containsKey、remove)
ConcurrentHashMap的弱一致性主要是为了提升效率,是一致性与效率之间的一种权衡。要成为强一致性,就得到处使用锁,甚至是全局锁,这就与Hashtable和同步的HashMap一样了。

ConcurrentLinkedQueue
链表的、无界的安全队列 
并发队列 先进先出 非阻塞队列
ConcurrentLinkedQueue的API原来.size()是要遍历一遍集合的,所以尽量要避免用size而改用isEmpty()
队列不允许null元素

LinkedBlockingQueue
基于链表的阻塞队列,其内部也维持着一个数据缓冲队列(该队列由一个链表构成),
当生产者往队列中放入一个数据时,队列会从生产者手中获取数据,并缓存在队列内部,而生产者立即返回;
只有当队列缓冲区达到最大值缓存容量时(LinkedBlockingQueue可以通过构造函数指定该值),
才会阻塞生产者队列,直到消费者从队列中消费掉一份数据,生产者线程会被唤醒,反之对于消费者这端的处理也基于同样的原理。
而LinkedBlockingQueue之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,
这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。
作为开发者,我们需要注意的是,如果构造一个LinkedBlockingQueue对象,而没有指定其容量大小,
LinkedBlockingQueue会默认一个类似无限大小的容量(Integer.MAX_VALUE),
这样的话,如果生产者的速度一旦大于消费者的速度,也许还没有等到队列满阻塞产生,系统内存就有可能已被消耗殆尽了。

ArrayBlockingQueue
ArrayBlockingQueue是一个由数组支持的有界阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。
队列的头部 是在队列中存在时间最长的元素,队列的尾部 是在队列中存在时间最短的元素。
新元素插入到队列的尾部,队列检索操作则是从队列头部开始获得元素。
         这是一个典型的“有界缓存区”,固定大小的数组在其中保持生产者插入的元素和使用者提取的元素。
         一旦创建了这样的缓存区,就不能再增加其容量。试图向已满队列中放入元素会导致放入操作受阻塞;
        试图从空队列中检索元素将导致类似阻塞。
   ArrayBlockingQueue创建的时候需要指定容量capacity(可以存储的最大的元素个数,因为它不会自动扩容)。

  PriorityBlockingQueue
        类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序
  
  SynchronousQueue
  Java 6的并发编程包中的SynchronousQueue是一个没有数据缓冲的BlockingQueue,
       生产者线程对其的插入操作put必须等待消费者的移除操作take,反过来也一样。
        不像ArrayBlockingQueue或LinkedListBlockingQueue,SynchronousQueue内部并没有数据缓存空间,
        你不能调用peek()方法来看队列中是否有数据元素,因为数据元素只有当你试着取走的时候才可能存在,
        不取走而只想偷窥一下是不行的,当然遍历这个队列的操作也是不允许的。队列头元素是第一个排队要插入数据的线程,
        而不是要交换的数据。数据是在配对的生产者和消费者线程之间直接传递的,并不会将数据缓冲数据到队列中。
        可以这样来理解:生产者和消费者互相等待对方,握手,然后一起离开。
        
linkedblockingdeque
  双向并发阻塞队列。所谓双向是指可以从队列的头和尾同时操作,并发只是线程安全的实现,
  阻塞允许在入队出队不满足条件时挂起线程,这里说的队列是指支持FIFO/FILO实现的链表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值