苦逼菜狗程序猿,用来总结和备忘,大家勿喷。
目录
ConcurrentLinkedQueue(无阻塞无界队列)的用法
jdk有两套实现(都是继承自接口Queue):
ConcurrentLinkedQueue(高性能并发Queue,无锁的方式实现的,性能好于BlockingQueue)
BlockingQueue(阻塞队列接口)
ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。
LinkedBlockingQueue:一个由链表结构组成的无界阻塞队列。
PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。
DealyQueue:一个带有延时时间的队列
SynchronousQueue:一个不存储元素的阻塞队列。
ConcurrentLinkedQueue(无阻塞无界队列)的用法
add() 和offer() 都是添加元素(非阻塞队列两个方法没有多大区别)
poll() 取出头元素并删除头元素
peek()取出元素但不删除
BlockingQueue(阻塞队列接口)的用法
offer(anObject)非阻塞添加元素,返回true和false
offer(E e, long timeout, TimeUnit unit) 指定时间内添加元素,如果添加成功返回true,不成功返回false
put(E e) 阻塞添加元素。如果队列没有空间,会一直阻塞到有空间添加元素为止
poll(long timeout, TimeUnit unit)指定时间内取出原属,取出元素返回true,否则返回false
take()阻塞取出队中的首位元素,如果队列内无元素会一直阻塞到有元素再继续
drainTo() 一次性取出队列中所有可用元素(也可以指定个数),通过改方法可以获取数据效率
模拟阻塞队列
- 队列代码
package org.cc; import java.util.Stack; public class MyBlockQuene<T> { private Stack<T> stack; // push的锁 private final static Object pushLock = new Object(); // pop的锁 private final static Object popLock = new Object(); public MyBlockQuene(){ stack=new Stack<T>(); } private static int MAX_SIZE=3; //插入元素 public void push(T t){ if(stack.size()>=3) lockPush(); else{ stack.push(t) ; unLockPop(); } } //取出元素 public T pop(){ T t= stack.pop(); if(stack.size()<3) unLockPush(); if(stack.size()==0) lockPop(); return t; } public void unLockPush(){ synchronized (pushLock) { pushLock.notify(); } } public void lockPush(){ synchronized (pushLock) { try { pushLock.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void unLockPop(){ synchronized (popLock) { popLock.notify(); } } public void lockPop(){ synchronized (popLock) { try { popLock.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
- 调用代码
package org.cc; public class UseMyBlockingQueue { public static void main(String[] args) throws InterruptedException { final MyBlockingQueue queue=new MyBlockingQueue<String>(3); queue.put("a"); queue.put("b"); queue.put("c"); Thread t1=new Thread(new Runnable() { public void run() { queue.put("e"); queue.put("f"); } }); Thread t2=new Thread(new Runnable() { public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } queue.take(); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } queue.take(); } }); t1.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } t2.start(); } }
- 调用结果
容容器中添加了一个元素a
容容器中添加了一个元素b
容容器中添加了一个元素c
容器中取出了一个元素a
容容器中添加了一个元素e
容器中取出了一个元素b
容容器中添加了一个元素f
从结果可以看出添加3个之后必须有容器被取出之后才能继续添加元素
主要队列的基本使用
- ConcurrentLinkedQueue
//无阻塞无界队列 ConcurrentLinkedDeque<String> clq=new ConcurrentLinkedDeque<String>(); clq.add("a"); //无阻塞队列add和offer没有区别。都是添加元素 clq.offer("b"); clq.offer("c"); System.out.println("clq容器当前长度:"+clq.size()); //从头部取出元素,并在容器中移除元素 System.out.println("poll从头部取出元素,并在容器中移除元素:"+clq.poll()); System.out.println("clq容器当前长度:"+clq.size()); System.out.println("peek从头部取出元素,但不移除元素:"+clq.peek()); System.out.println("clq容器当前长度:"+clq.size());
运行结果
clq容器当前长度:3
poll从头部取出元素,并在容器中移除元素:a
clq容器当前长度:2
peek从头部取出元素,但不移除元素:b
clq容器当前长度:2
-
ArrayBlockingQueue和LinkedBlockingQueue
//基于数组的阻塞有界队列ArrayBlockingQueue //基于链表的阻塞无界队列LinkedBlockingDeque //两者用法相似,LinkedBlockingDeque将不在演示 ArrayBlockingQueue<String> abq=new ArrayBlockingQueue<String>(3); abq.add("a"); abq.add("b"); abq.add("c"); System.out.println("offer会返回是否添加成功:"+abq.offer("f", 2, TimeUnit.SECONDS)); ArrayBlockingQueue<String> abq1=new ArrayBlockingQueue<String>(3); abq.drainTo(abq1, 2); for(Iterator iterator=abq1.iterator(); iterator.hasNext();){ System.out.println((String)iterator.next()); }
运行结果
offer会返回是否添加成功:false
取出元素:a
取出元素:b -
SynchronousQueue(不存元素的阻塞队列。必须先取再添加)
//不能直接添加元素,否则会报错,必须现有去元素方法 //Exception in thread "main" java.lang.IllegalStateException: Queue full //sq.add("f"); new Thread(()->{ try { System.out.println("取出元素:"+sq.take()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }).start(); new Thread(()->{ System.out.println("添加元素是否成功:"+sq.add("f")); }).start();
运行结果
添加元素是否成功:true
取出元素:f -
PriorityBlockingQueue优先级阻塞队列
注:插入或取出后队列都不会对整体重新排序,只保证每次取出来是按照Comparable接口的实现取出优先级最高的
package org.cc; /** * 实现Compareble接口 * @author Machenike * */ public class PriorityNode implements Comparable<PriorityNode>{ private Integer id; private String name; public PriorityNode(Integer id,String name){ this.id=id; this.name=name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int compareTo(PriorityNode o) { return id>o.id?1:(id==o.id?0:-1); } @Override public String toString() { // TODO Auto-generated method stub return id+":"+name; } }
PriorityBlockingQueue<PriorityNode> pbq=new PriorityBlockingQueue(); pbq.add(new PriorityNode(2,"name3")); pbq.add(new PriorityNode(3,"name3")); pbq.add(new PriorityNode(4,"name4")); pbq.add(new PriorityNode(1,"name1")); System.out.println(pbq.toString()); System.err.println("0 容器为: " + pbq); System.err.println("1 获取元素: " + pbq.take().getId()); System.err.println("1 容器为: " + pbq); System.err.println("2 获取元素: " + pbq.take().getId()); System.err.println("2 容器为: " + pbq); System.err.println("3 获取元素: " + pbq.take().getId()); System.err.println("3 容器为: " + pbq); System.err.println("4 获取元素: " + pbq.take().getId())
-
DelayQueue延时队列
元素需要继承java.util.concurrent.Delayed接口
模拟订单自动取消功能package org.cc; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; public class Order implements Delayed{ private Integer id; private String name; private long endTime;//订单自动取消时间 public Order(Integer id, String name,long endTime) { this.id = id; this.name = name; this.endTime=endTime; } private final TimeUnit timeUnit=TimeUnit.SECONDS; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int compareTo(Delayed o) { Order w = (Order)o; return this.getDelay(timeUnit) - w.getDelay(timeUnit) > 0 ? 1 : 0; } @Override public long getDelay(TimeUnit unit) { // TODO Auto-generated method stub return endTime-System.currentTimeMillis(); } }
package org.cc; import java.util.concurrent.DelayQueue; public class User implements Runnable{ private DelayQueue<Order> dq=new DelayQueue<>(); //下单 public void preOrder(Integer id,String name,long endTime){ Order o=new Order(id,name,endTime); dq.add(o); System.out.println("已创建订单:"+name+",请尽快付款。"); } public void orderCancel(Order o) { System.out.println("你的订单"+o.getName()+"已自动取消!"); } @Override public void run() { // TODO Auto-generated method stub while(true){ try { orderCancel(dq.take()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { User user=new User(); user.preOrder(2, "订单二", 1000+System.currentTimeMillis()); user.preOrder(3, "订单三", 2000+System.currentTimeMillis()); user.preOrder(1, "订单一", 3000+System.currentTimeMillis()); new Thread(user).start(); } }
运行结果