標籤:鏈表實現 exception 頭部 同步 mil 緩衝系統 數組 任務調度 lin
JDK提供了7中阻塞隊列,這裡介紹其中3中,剩餘的以此類推原理相同。
1.ArrayBlockingQueue
package com.seeyon.queue;import java.util.concurrent.ArrayBlockingQueue;/** * Created by yangyu on 16/11/27. *//** * ArrayBlockingQueue是數組結構組成的有界阻塞隊列 * 當隊列已經滿了的時候,put操作會阻塞當前線程,直到隊列發生出隊操作然後會喚醒put線程在入隊 * 當隊列為空白的時候,take操作會阻塞當前線程,直到隊列發生入隊操作後會喚醒take線程進行出隊 */public class TestArrayBlockingQueue { public static void main(String[] args) { ArrayBlockingQueue<String> queue = new ArrayBlockingQueue(1); try { queue.put("1111"); /** * 該操作會被阻塞,知道隊列發生出隊操作 */ queue.put("2222"); } catch (InterruptedException e) { e.printStackTrace(); } }}
2.LinkedBlockingQueue:鏈表實現的有界阻塞隊列
3.PriorityBlockingQueue:支援優先順序的無界阻塞隊列
4.DelayQueue
package com.seeyon.queue;import java.util.concurrent.DelayQueue;import java.util.concurrent.Delayed;import java.util.concurrent.TimeUnit;import static java.util.concurrent.TimeUnit.NANOSECONDS;/** * Created by yangyu on 16/11/27. *//** * DelayQueue是一個支援延時擷取元素的無界隊列 * DelayQueue可以用於如下情境: * 1.緩衝系統的的設計:用DelayQueue儲存緩衝元素的有效期間,用一個線程迴圈查詢DelayQueue,一旦能從DelayQueue中擷取到元素,說明該元素到期了 * 2.定時任務調度:使用DelayQueue儲存當天會執行的任務和執行時間,一旦從DelayQueue中擷取到任務就開始執行,TimerQueue就是使用DelayQueue實現的 * DelayQueue的原理: * 1.當線程put元素的時候,DelayQueue會對你put的元素通過其本身的compareTo方法進行排序,延時時間越短的順序越靠近隊列頭部 * 2.當線程take元素的時候,DelayQueue會檢測當前是否有Thread已經在等待隊頭元素了,如果有的話,那麼只能阻塞當前前程,等已經取到隊頭 * 的Thread完成以後再喚醒。 * 如果沒有Thread在等待隊頭元素的話,那麼會查詢一下隊頭元素還剩多少Delay時間,並且將當前線程設定為隊頭等待線程,然後讓當前線程wait剩餘 * Delay時間後在來擷取隊頭元素。 */public class TestDelayQueue { public static void main(String[] args) { DelayQueue<Message> delayQueue = new DelayQueue<>(); delayQueue.put(new Message(2000,"yangyu")); try { System.out.println(delayQueue.take()); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("end"); } private static class Message implements Delayed{ private long nanoTime; private String data; Message(long millisTime ,String data){ this.nanoTime = now()+millisTime*(1000*1000); this.data = data; } private final long now(){ return System.nanoTime(); } @Override public long getDelay(TimeUnit unit) { return unit.convert(nanoTime - now(), NANOSECONDS); } @Override public int compareTo(Delayed other) { if (other == this) // compare zero if same object return 0; if (other instanceof Message) { Message x = (Message) other; long diff = nanoTime - x.nanoTime; if (diff < 0) return -1; else if (diff > 0) return 1; else return 1; } long diff = getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS); return (diff < 0) ? -1 : (diff > 0) ? 1 : 0; } }}
5.SynchronousQueue
package com.seeyon.queue;import java.util.concurrent.SynchronousQueue;/** * Created by yangyu on 16/11/27. *//** * SynchronousQueue是一個不儲存資料的隊列,只是做資料的的傳遞工作 * 同步隊列,一個put操作必須等待一個take操作,否則線程被阻塞 * 同樣,一個take操作必須等待一個put操作,否則線程被阻塞 */public class TestSynchronousQueue { public static void main(String[] args) { SynchronousQueue<String> strings = new SynchronousQueue<>(); Thread t =new Thread(()->{ try { /** * 該take操作會被阻塞,直到後面的strings.put("yangyu")操作後,當前線程才會被喚醒 */ System.out.println(strings.take()); } catch (InterruptedException e) { e.printStackTrace(); } }); t.start(); try { Thread.sleep(2000); /** * 喚醒阻塞線程並且傳遞資料 */ strings.put("yangyu"); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("完成"); }}
6.LinkedTransferQueue
7.LinkedBlockingDeqeue:是一個鏈表結構組成的雙向阻塞隊列,可以從隊列的兩端插入或者移出元素。
Java--concurrent並發包下阻塞隊列介紹