21-使用并发数据结构替代手动编程
11.7 使用并发数据结构替代手动编程
数据结构是程序的重要组成部分。我们要管理存储在各种各样数据结构中的数据。数组、列表或树都是常用的数据结构。Java API提供了大量随手可用的数据结构,但在并发程序中,必须小心使用它们,因为不是所有数据结构都是 线程安全 的。如果使用了线程不安全的数据结构,那么就可能在并发程序中产生数据不一致问题。
当需要在并发程序中使用数据结构时,请查看其实现类的文档,确认它是否支持并发操作。Java提供了如下两种支持并发的数据结构。
- 非阻塞数据结构: 在数据结构已满或为空时,这类数据结构的插入和取出操作会因无法完成而返回
null
。 - 阻塞数据结构: 这类数据结构提供了和非阻塞数据结构提供相同的操作。另外,它们还提供了能在插入和取出无法立即完成时,将线程阻塞的操作,直到可以完成时。
下面是一些Java API提供的数据结构,它们可以在并发应用程序中使用。
ConcurrentLinkedDeque
:它是一种基于链表的非阻塞数据结构,可以在其头部和尾部插入数据。LinkedBlockingDeque
:它是一种固定大小的基于链表的阻塞数据结构,可以在其头部和尾部插入元素。当它提供的操作无法立即完成时,将阻塞线程,直到它可以完成。ConcurrentLinkedQueue
:它是一种非阻塞队列,可以在其尾部插入元素,并在头部取出。ArrayBlockingQueue
:它是一种固定大小的阻塞队列,可以在其尾部插入元素,并在头部取出。它提供的操作因为队列已满或为空而无法完成时,将使线程进入休眠状态,直到可以完成时。LinkedBlockingQueue
:它是一个阻塞队列,可以在其尾部插入元素,在其头部取出。它所提供的操作,如果因为队列已满或为空而无法完成时,那么将使线程进入休眠状态,直到可以完成。DelayQueue
:它是带有延迟元素的LinkedBlockingQueue
队列。每个插入的元素都必须实现Delayed
接口。元素的延迟时间为0时才能取出。LinkedTransferQueue
:它是一个阻塞队列,提供可以实现生产者/消费者模式的操作。在这些操作因为队列已满或为空而无法完成时,线程将进入休眠状态,直到可以完成。PriorityBlockingQueue
:它是一个阻塞队列,根据优先级对元素进行排序。所有插入到队列中的元素都必须实现Comparable
接口。compareTo()
方法的返回值决定了队列中元素的位置。和所有的阻塞数据结构一样,它提供的操作如果无法立即完成,那么就将导致线程进入休眠状态,直到可以完成时。SynchronousQueue
:它是一个阻塞队列,每次插入操作都必须等待另一个线程的移除操作,这两个操作必须同时完成。ConcurrentHashMap
:它是一类支持并发、无需阻塞执行的HashMap
。ConcurrentSkipListMap
:这种数据结构把key
和value
关联起来。每个key
只有一个value
。它以有序的方式存储key
,提供了从map
中查找并获取元素的方法。它是非阻塞的数据结构。