苦逼菜狗程序猿,用來總結和備忘,大家勿噴。
目錄
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(); } }
運行結果