首页 > 编程语言 >JUC12 java并发编程容器

JUC12 java并发编程容器

时间:2022-12-08 12:01:08浏览次数:64  
标签:编程 java 消费者 队列 元素 阻塞 JUC12 线程 DelayQueue


0. java容器类

​​JAVA容器详解_诗酒趁年华527的博客

​​Java 容器详解 - _情书 -

​一文秒懂java容器大全 - 知乎​

Collection: List, Set, Queue

Map:

2. java并发容器类

JUC12 java并发编程容器_服务器

3. 常用容器类详解

3.1 Concurrent

3.1.1 ConcurrentHashMap

原理: 锁分段

如果要实现一个线程安全的队列有两种方式:一种是使用阻塞算法,另一种是使用非阻塞算法。
 

3.1.2 ConcurrentLinkedQueue

原理: CAS算法,非阻塞算法。

3.2 阻塞队列

​Java阻塞队列ArrayBlockingQueue和LinkedBlockingQueue实现原理分析 | Format's Notes​

​​聊聊并发(七)——Java中的阻塞队列_Java_方腾飞_InfoQ精选文章​​

JUC12 java并发编程容器_java_02

1)ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列(公平、非公平)
用数组实现的有界阻塞队列。此队列按照先进先出(FIFO)的原则对元素进行排序。 默认情况下不保证访问者公平的访问队列,所谓公平访问队列是指阻塞的所有生产者线程或消费者线程,当队列可用时,可以按照阻塞的先后顺序访问队列,即先阻塞的生产者线程,可以先往队列里插入元素,先阻塞的消费者线程,可以先从队列里获取元素。通常情况下为了保证公平性会降低吞吐量。
2)LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列(两个独立锁提高并发)
基于链表的阻塞队列,同 ArrayListBlockingQueue 类似,此队列按照先进先出(FIFO)的原则对元素进行排序。而 LinkedBlockingQueue 之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。LinkedBlockingQueue 会默认一个类似无限大小的容量(Integer.MAX_VALUE)
3)PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列(compareTo 排序实现优先)
是一个支持优先级的无界队列。默认情况下元素采取自然顺序升序排列。 可以自定义实现compareTo() 方法来指定元素进行排序规则,或者初始化 PriorityBlockingQueue 时,指定构造
参数 Comparator 来对元素进行排序。需要注意的是不能保证同优先级元素的顺序。
4)DelayQueue:一个使用优先级队列实现的无界阻塞队列(缓存失效、定时任务 )
是一个支持延时获取元素的无界阻塞队列。队列使用 PriorityQueue 来实现。队列中的元素必须实
现 Delayed 接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才
能从队列中提取元素。我们可以将 DelayQueue 运用在以下应用场景:
4.1) 缓存系统的设计:可以用 DelayQueue 保存缓存元素的有效期,使用一个线程循环查询
DelayQueue,一旦能从 DelayQueue 中获取元素时,表示缓存有效期到了。
4.2) 定 时 任 务 调 度 : 使 用 DelayQueue 保 存 当 天 将 会 执 行 的 任 务 和 执 行 时 间 , 一 旦 从 DelayQueue 中获取到任务就开始执行,从比如 TimerQueue 就是使用 DelayQueue 实现的
5)SynchronousQueue:一个不存储元素的阻塞队列(不存储数据、可用于传递数据)
是一个不存储元素的阻塞队列。每一个 put 操作必须等待一个 take 操作,否则不能继续添加元素。SynchronousQueue 可以看成是一个传球手,负责把生产者线程处理的数据直接传递给消费者线程。队列本身并不存储任何元素,非常适合于传递性场景,比如在一个线程中使用的数据,传递给另 外 一 个 线 程 使 用 , SynchronousQueue 的 吞 吐 量 高 于 LinkedBlockingQueue 和
ArrayBlockingQueue。
6)LinkedTransferQueue:一个由链表结构组成的无界阻塞队列是 一 个 由 链 表 结 构 组 成 的 无 界 阻 塞 TransferQueue 队 列 。 相 对 于 其 他 阻 塞 队 列 ,
LinkedTransferQueue 多了 tryTransfer 和 transfer 方法。
6.1) transfer 方法: 如果当前有消费者正在等待接收元素(消费者使用 take()方法或带时间限制的poll()方法时), transfer 方法可以把生产者传入的元素立刻 transfer(传输)给消费者。如
果没有消费者在等待接收元素, transfer 方法会将元素存放在队列的 tail 节点,并等到该元素
被消费者消费了才返回。
6.2) tryTransfer 方法。则是用来试探下生产者传入的元素是否能直接传给消费者。如果没有消费
者等待接收元素,则返回 false。和 transfer 方法的区别是 tryTransfer 方法无论消费者是否
接收,方法立即返回。而 transfer 方法是必须等到消费者消费了才返回。
对于带有时间限制的 tryTransfer(E e, long timeout, TimeUnit unit)方法,则是试图把生产者传
入的元素直接传给消费者,但是如果没有消费者消费该元素则等待指定的时间再返回,如果超时
还没消费元素,则返回 false,如果在超时时间内消费了元素,则返回 true。
7)LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列

是一个由链表结构组成的双向阻塞队列。所谓双向队列指的你可以从队列的两端插入和移出元素。
双端队列因为多了一个操作队列的入口,在多线程同时入队时,也就减少了一半的竞争。相比其
他的阻塞队列, LinkedBlockingDeque 多了 addFirst, addLast, offerFirst, offerLast,peekFirst, peekLast 等方法,以 First 单词结尾的方法,表示插入,获取(peek)或移除双端队
列的第一个元素。以 Last 单词结尾的方法,表示插入,获取或移除双端队列的最后一个元素。另
外插入方法 add 等同于 addLast,移除方法 remove 等效于 removeFirst。但是 take 方法却等同
于 takeFirst,不知道是不是 Jdk 的 bug,使用时还是用带有 First 和 Last 后缀的方法更清楚。
在初始化 LinkedBlockingDeque 时可以设置容量防止其过渡膨胀。另外双向阻塞队列可以运用在
“工作窃取”模式中。
 

阻塞队列不可用时的四种处理方式:

JUC12 java并发编程容器_服务器_03

抛出异常:抛出一个异常;
返回特殊值:返回一个特殊值(null 或 false,视情况而定)
一直阻塞:在成功操作之前,一直阻塞线程
超时退出:放弃前只在最大的时间内阻塞
 

阻塞队列来实现生产者-消费者模型?
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。
这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当
队列满时,存储元素的线程会等待队列可用。
阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消
费者是从队列里拿元素的线程
。阻塞队列就是生产者存放元素的容器,而消费者
也只从容器里拿元素。
 

3.3 CopyOnWrite

3.3.1 CopyOnWriteArrayList

3.3.2 CopyOnWriteArraySet

标签:编程,java,消费者,队列,元素,阻塞,JUC12,线程,DelayQueue
From: https://blog.51cto.com/u_15905340/5920887

相关文章