ConcurrentLinkedQueue(无界队列):
//1.高性能的无阻塞无界队列ConcurrentLinkedQueue
//无界队列不用定义长度
ConcurrentLinkedQueue<String> clq = new ConcurrentLinkedQueue();
//添加元素有两种方法offer()和add(),他们没有区别
clq.offer("a");
clq.add("b");
clq.add("c");
clq.add("d");
//获取数据,使用poll()获取头部数据,并且将头部数据移除
System.out.println("头部取出元素:"+clq.poll());//从头部取出一个元素,并且从容器本身移除
System.out.println("容器长度:"+clq.size());
System.out.println("头部取出元素:"+clq.peek());//从头部取出一个元素,但不会从容器本身移除
System.out.println("容器长度:"+clq.size());
ArrayBlockingQueue(有界队列):基于数组的阻塞队列实现,在ArrayBlockingQueue内部维护了一个有限长度的数组(即定长数组),以便缓存对列中的数据对象,其内部没有实现读写分离,也就意味着生产和消费不能完全并行,其长度是需要定义的,可以指定先进先出(FIFO),其属于有界队列,应用场景很多。
//2.基于阻塞- 有界队列ArrayBlockingQueue,需要定义长度ArrayBlockingQueue<>(5)
/*其为有界队列,单线程操作,不支持高并发
* 不能实现生产和消费并行*/
//ArrayBlockingQueue内部结构是维护这一个有界的数组
ArrayBlockingQueue<String> abq = new ArrayBlockingQueue<>(5);
//添加元素
abq.put("a");
abq.add("b");
abq.add("c");
abq.add("d");
abq.add("e");
//使用offer添加元素,如果可以添加返回true,如果不可以返回false,此处应用带有延迟时间和时间戳的offer方法
System.out.println(abq.offer("f", 2, TimeUnit.SECONDS));
//应用drainTo进行队列拷贝
ArrayBlockingQueue<String> abq1 = new ArrayBlockingQueue<>(5);
abq.drainTo(abq1,3);//将abq容器中的元素拷贝3个到abq1中
//循环队列
for(Iterator iterator = abq1.iterator();iterator.hasNext();) {
String string = (String) iterator.next();
System.out.println("元素:"+string);
}
LinkedBlockingQueue:基于链表的阻塞队列,同ArrayBlockingQueue类似,其内部也维持着一个数据缓冲队列(该队列由一个链表构成),LinkedBlockingQueue之所以能够高效的处理并发数据,是因为其内部实现采用分离锁(读写分离两个锁),从而实现生产者和消费者操作的完全并行运行,他是一个无界队列。
/*3.基于阻塞- 无界队列LinkedBlockingQueue
* 基于链表的阻塞队列LinkedBlockingQueue,内部维护着链表,
* 能够高效处理并发数据,其内部实现分离锁(读写分离两个锁),从而
* 实现生产者和消费者操作完全并行;
* 使用方法基本等同于ArrayBlockingQueue
*/
LinkedBlockingQueue<String> lbq = new LinkedBlockingQueue<>();
lbq.put("a");
lbq.add("b");
lbq.add("c");
lbq.add("d");
lbq.add("e");
lbq.add("f");
lbq.add("g");
System.out.println(lbq.offer("h", 1, TimeUnit.SECONDS));
System.out.println("容器大小"+lbq.size());
System.out.println("poll()从头部取出元素"+lbq.poll());
System.out.println("poll方法取出元素后容器大小"+lbq.size());
System.out.println("peek()从头部取出元素"+lbq.peek());
System.out.println("peek方法取出元素后容器大小"+lbq.size());
LinkedBlockingQueue<String> lbq1 = new LinkedBlockingQueue<>();
lbq.drainTo(lbq1,3);
for(Iterator iterator = lbq1.iterator();iterator.hasNext();) {
String string = (String) iterator.next();
System.out.println("lbq1元素:"+string);
}
SynchronousQueue :一种没有缓冲的队列,生产者产生的数据直接会被消费者获取并消费。
/*4.没有缓存的队列 SynchronousQueue(不能盛放任何元素的阻塞队列)
* 生产者生产的数据直接会被消费者获取并消费
* 它同时也是一种阻塞队列
* 实现快速的获取与投递机制:正常场景下必须有一个A获取元素线程阻塞在容器中,
* 然后B投递元素线程投递后激活A线程完成获取;如果B投递线程先投递就会出现异常;
*/
SynchronousQueue<String> sq = new SynchronousQueue();
//sq.add("a");//直接添加报 Queue full异常
//定义获取元素的线程并启动,进入等待
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
//线程要先获取元素
try {
System.out.println("元素内容"+sq.take());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
},"t1").start();
//定义添加元素的线程,并激活获取元素的线程
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
sq.add("a");
}
},"t2").start();
}
关于阻塞队列与非阻塞队列可以参考:https://blog.csdn.net/danengbinggan33/article/details/73105838