1、ConcurrentLinkedQueue
在并发编程中,有时候需要使用线程安全的队列。
如果要实现一个线程安全的队列有两种方式:一种是使用阻塞算法,另一种是非阻塞算法。
使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现。
非阻塞算法的实现方式可以使用循环CAS的方式来实现。
ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部;当我们获取一个元素时,它会返回队列头部的元素。它采用了"wait-free“算法(即CAS算法)来实现。
2、Java中的阻塞队列
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法。
a、支持阻塞的插入方法:当队列满时,队列会阻塞插入元素的线程,直到队列不满。
b、支持阻塞的移除方法:在队列为空时,获取元素的线程会等待队列变为非空。
阻塞队列常用于生产者和消费者的场景。
JDK7提供了7个阻塞队列:
ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。
LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。
PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。
DelayQueue:一个使用优先级队列实现的无界阻塞队列。支持延时获取元素。非常有用,可以用来设计缓存系统和定时任务调度。
SynchronousQueue:一个不存储元素的阻塞队列。每一个put操作必须等待一个take操作,否则不能继续添加元素。适合传递性场景。
LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。
3、Fork/Join框架
该框架是Java 7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。
Fork就是把一个大任务切分为若干子任务并行的执行。Join就是合并这些子任务的执行结果,最后得到这个大任务的结果。
工作窃取算法是指某个线程从其他队列里窃取任务来执行。
使用两个类来完成任务:
a、ForkJoinTask:要使用ForkJoin框架,必须首先创建一个ForkJoin任务。它提供在任务中执行fork()和join()操作的机制。通常情况下,我们不需要直接继承ForkJoinTask类,只需要继承它的子类:
RecursiveAction:用于没有返回结果的任务。
RecursiveTask:用于有返回结果的任务。
b、ForkJoinPool:ForkJoinTask需要通过ForkJoinPool来执行。
ForkJoinPool由ForkJoinTask数组和ForkJoinWorkerThread数组组成,ForkJoinTask数组负责将存放程序提交给ForkJoinPool的任务,而ForkJoinWorkerThread数组负责执行这些任务。