高併發程式設計:併發Queue介面
阿新 • • 發佈:2018-11-08
佇列是一種先進先出或者後進後出的資料結構。在此我們模擬一下佇列這種資料結構:
MyQueue.java定義如下:
public class MyQueue { //佇列的容器 private LinkedList<Object> list = new LinkedList<Object>(); //計數器 int count private final AtomicInteger count = new AtomicInteger(0); //最大容量 private int maxSize; //最小容量 private int minSize = 0; //鎖 private final Object lock = new Object(); public MyQueue() { this(16); } public MyQueue(int maxSize) { this.maxSize = maxSize; } public void put(Object obj) { synchronized (lock) { while(count.get() == maxSize) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } list.add(obj); //將新的元素新增到容器裡 System.out.println("新增前容器長度:" + count.get()); count.getAndIncrement(); System.out.println("新增後容器長度:" + count.get()); lock.notify(); //喚醒執行緒 } } public Object take() { Object temp = null; synchronized (lock) { while(count.get() == minSize) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } temp = list.removeFirst(); //從容器中移除第一個元素 System.out.println("自減之前的長度:" + count.get()); count.getAndDecrement(); System.out.println("自減之後的長度:" + count.get()); lock.notify(); } return temp; } public int size() { return count.get(); } public List<Object> getQueueList() { return list; } }
該佇列的資料結構為一個List< Object> 作為容器來盛裝資料,此外還有幾個變數,分別是count計數器和maxSize,minSize最大最小容量的標誌,此外還有lock鎖。此類有3個核心方法,分別是size()返回佇列長度的方法,take()移除節點方法和put()新增節點方法。
該佇列的測試類定義如下:
public class TestMyQueue { public static void main(String[] args) throws Exception { MyQueue queue = new MyQueue(5); queue.put("A"); queue.put("B"); queue.put("C"); queue.put("D"); queue.put("E"); System.out.println("主執行緒queue : " + queue); Thread t1 = new Thread(new Runnable() { @Override public void run() { queue.put("F"); queue.put("G"); } }, "t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); queue.take(); Thread.sleep(1000); queue.take(); }catch (InterruptedException e) { e.printStackTrace(); } } }, "t2"); t1.start(); Thread.sleep(1000); t2.start(); Thread.sleep(5000); List<Object> elements = queue.getQueueList(); for(Object obj : elements) { System.out.print(obj.toString() + " "); } } }
該測試類除了main函式所在的主執行緒之外還存在兩個子執行緒t1,t2。執行緒t1負責向容器大小為5的佇列容器放入"F"和"G"元素,執行緒t2則負責向佇列移除頭部節點。
輸出結果如下:
主執行緒queue : [email protected]
C D E F G