1、ArrayDeque
Deque接口的一种可改变大小的实现,数组deque没有容量限制,可以根据需要增加容量。是非线程安全的;如果没有外同步,它不支持多线程的并发访问。不允许元素为null,该类用作栈或队列时,比Stack和LinkedList都要快。ArrayDeque的大多数操作需要分摊的常量时间复杂度(amortezed constant time),例外的有remove、removeFirstOccurrence、removeLastOccurrence、contains和iterator.remove()方法,以及批量操作,所有这些都是只需要线性时间复杂度(linear time)。
迭代器的返回通过使用iterator方法是快速失败的(fast-fail) ,即如果创建iterator后,deque在任何时间被除了迭代器自己的remove方法修改了,iterator通常会抛出ConcurrentModificationException异常。因此,对于并发修改,迭代器会快速干净地失败,而不会产生任何危害,当未来在不确定的时间发生不确定性的行为。注意,迭代器的fail-fast行为并不能硬性地保证任何非同步的并发修改时都会发生,fail-fast在最大努力的基础上抛出ConcurrentModificationException异常。因此,如果程序依赖于作为判断正确与否的依据是不正确的,fail-fast只能用作检测错误。
该类和其迭代器实现了Collection接口和Iterator接口的所有可选方法。
2、ConcurrentLinkedListDeque
一种基于链表的无边界的并发Deque。并发插入、移除和访问操作通过多线程安全执行。一个ConcurrentLinkedDeque是当多线程共享访问一个公共集合的有效选择。像多数其他并发集合实现一样,该类并不允许元素为null。
iterators和spliterators是弱一致的。
注意:不像多数集合,size方法并不是一个常量时间复杂度的操作,因为deques的异步特性,决定当前元素的个数需要对所有元素遍历一遍,并且可能会获得不准确的结果,当在遍历期间该集合被修改。另外,批量操作addAll、removeAll、retainAll、containsAll、equals和toArray方法并不能保证是原子操作,例如,一个迭代器操作并发地与一个addAll操作执行,可能只能查看到部分加入的元素。
该类和它的迭代器实现了Deque和Iterator接口的所有可选方法。
Memory consistency effects(内存一致性效果):和其他并发集合一样,线程中的将一个元素放进ConcurrentLinkedDeque的行为比另一个线程中访问或移除一个元素的优先级高。
注意问题:
1)如果使用ConcurrentLinkedDeque, 是否意味着我们不需要自己进行任何同步或加锁操作?
并发集合的原子操作是同步的,换句话说就是每个对queue的单独调用是保证线程安全的,当执行非原子操作时,并不能保证线程安全的。例如只执行queue.add(e)或queue.poll()是线程安全的。但是非原子调用则不是自动线程安全的,如下段代码:
if(!queue.isEmpty()) {
queue.poll(obj);
}
在queue.isEmpty()和queue.poll()之间可能会发生其他线程增加或移除元素,此时就需要自己增加同步锁:
Syncronized(queue) {
if(!queue.isEmpty()) {
queue.poll(obj);
}
}
2)当同时有1000个请求时,能保证该类不会丢失吗?
因为该类是一种无界限实现,所以无论你有多少同时发出的请求,queue不会遗失任何请求,因为queue的并发性,可能会超内存之类的,但队列本身实现不会成为限制因素的。在一个web应用中,可能会有其他丢失请求的可能,但queue的同步性不会成为原因之一。
3)该类执行效果如何?
通常,我们会讨论并发的正确性,也就是说,并发类保证它们是线程安全的(或者具有鲁棒性,不会出现死锁和饥饿等情况),对执行操作不做任何保证,而只是保证它们都是正确的。然而,ConcurrentLinkedDeque是一种wait-free实现,因此可能是性能最好的选择。
3、IdentityLinkedList
4、LinkedList
List和Deque接口的双向链表列表实现,实现了所有可选列表操作,且允许所有类型的元素(包括null)。所有操作对于一个双向链表列表来说都可以实现,索引到列表中某个元素的操作可以同从列表中距给定索引最近的列表的首或尾开始遍历。
注意该实现不是同步的,如果多线程并发地访问一个链表,并且至少有一个线程改变列表结构,则必须增加外部同步。这通常经过同步一些封装该列表的对象来实现。如果没有此类对象,则该列表必须用Collections.synchronizedList来包装,最好在创建时完成,以避免对列表意外的非同步访问。
该类的方法iterator和listIterator返回的迭代器也是fail-fast的。
5、ListAdapter