本文共 4272 字,大约阅读时间需要 14 分钟。
在并发队列上,JDK提供了两套实现,一个是以ConcurrentLinkedQueue为代表的高性能队列,一个是以BlockingQueue接口为代表的阻塞队列,无论哪种都继承自Queue。
是一种适用于高并发场景下的队列,通过无锁的方式,实现了高并发状态下的高性能,通常ConcurrentLinkedQueue性能好于BlockingQueue。它是一个基于链表的无界线程安全的队列。该队列的元素遵循先进先出的原则,头是最先进入的,尾是最近加入的,该队列不允许Null元素。ConcurrentLinkedQueue重要方法:
public class UserConcurrentLinkedQueue { public static void main(String[] args) { Queuequeue = new ConcurrentLinkedQueue<>(); queue.add("a"); queue.offer("b"); queue.offer("c"); queue.offer("d"); System.out.println(queue.poll()); //a 从头部取出元素,并从队列中删除 System.out.println(queue.size()); //3 System.out.println(queue.peek()); //b System.out.println(queue.size()); //3 }}
ArrayBlockingQueue:
基于数组的阻塞队列实现,在ArrayBlockingQueue内部,维护了一个定长数组,以便缓存队列中的数据对象,其内部实现读写分离,也就意味着生产和消费不能完全并行,长度是需要定义的,可以指定先进先出或者先进后出,也叫有界队列,在很多场景非常适合使用。LinkedBlockingQueue:
基于链表的阻塞实现,同ArrayBlockingQueue类似,其内部也维持着一个数据缓冲队列(该队列由一个链表构成),LinkedBlockingQueue之所以能够高效的处理并发数据,是因为其内部采用分离锁(读写分离两个锁),从而实现生产者和消费者操作的完全并行运行。它是一个无界队列。SynchronousQueue:
一种没有缓冲的队列,生产者的数据直接会被消费者获取并消费掉。public class UseQueue { public static void main(String[] args) throws InterruptedException { ArrayBlockingQueuequeue = new ArrayBlockingQueue<>(5); queue.offer("a"); queue.put("b");; queue.add("c"); queue.offer("d"); queue.offer("f"); System.out.println(queue.offer("g", 2, TimeUnit.SECONDS)); }}/* * 打印结果: * false * */
public class UseQueue { public static void main(String[] args) throws InterruptedException { LinkedBlockingQueuequeue = new LinkedBlockingQueue<>(); //不传参数就是无界队列 queue.add("a"); queue.add("b"); queue.offer("c"); queue.put("d"); queue.add("f"); for(Iterator iterator = queue.iterator(); iterator.hasNext();){ String str = iterator.next(); System.out.println(str); } }}/* * 打印结果: * a * b * c * d * f * */
public class UsePriorityBlockingQueue { public static void main(String[] args) throws InterruptedException { PriorityBlockingQueuetask = new PriorityBlockingQueue<>(); //在调用add方法时不排序 task.add(new Task(5,"t1")); task.add(new Task(1,"t2")); task.add(new Task(3,"t3")); //调用take方法时排序 System.out.println(task); System.out.println(task.take()); System.out.println(task); System.out.println(task.take()); System.out.println(task); System.out.println(task.take()); }}/**打印结果[5 , t1, 1 , t2, 3 , t3]5 , t1[3 , t3, 1 , t2]3 , t3[1 , t2]1 , t2* */
public class Task implements Comparable{ private int id; private String name; public Task(int id,String name){ this.id = id; this.name= name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return this.getId()+" , "+this.getName(); } @Override public int compareTo(Task paramT) { return paramT.getId() > this.getId() ? 1:(paramT.getId() < this.getId() ? -1 : 0); }}
Deque允许在队列的头部和尾部进行出兑和入队操作。LinkedBlockingDeque是一个线程安全的双端队列,可以说他是最为复杂的一种队列,在内部实现维护了前端和后端节点,但是其没有实现读写分离,因此同一时间只能有一个线程对其操作。在高并发中性能远低于其他BlockingQueue。更低于ConcurrentLinkedQueue,在JDK早期有一个非线程安全的Deque就是ArrayDeque了,java6里添加了LinkedBlockingDeque来弥补多线程场景下线程安全的问题。
转载地址:http://dbkni.baihongyu.com/