[大白裝逼]java阻塞隊(duì)列

前言

java提供了很多阻塞隊(duì)列,在平時(shí)的開發(fā)中也會使用到,所以在此對java提供的阻塞隊(duì)列進(jìn)行一個(gè)了解總結(jié)

首先

java的阻塞隊(duì)列都繼承與BlockingQueue,其有共同的方法
boolean offer(Object o);//將數(shù)據(jù)o加入隊(duì)列中,加入成功返回true,失敗則為false,此方法不阻塞
boolean offer(Object o,long timeout,TimeUnit unit);//將o加入隊(duì)列中,若timeout過后為未加入成功返回false,否則返回true,此方法會阻塞等待,unit為時(shí)間單位
put(Object o);//將數(shù)據(jù)o加入隊(duì)列中,若隊(duì)列沒有空間則會阻塞當(dāng)前的線程進(jìn)行等待
Object poll();//取走隊(duì)列頭部的數(shù)據(jù),如取不出則返回null
Object poll(long timeout,TimeUnit unit);//取走隊(duì)列頭部的數(shù)據(jù),若取不出則等待timeout,等待后取不出返回null
Object take();//取出隊(duì)列首部數(shù)據(jù),若取不出則阻塞直到取出來
int drainTo(Collection c);//取出隊(duì)列中所有數(shù)據(jù)放到容器c中,其中的排序?yàn)殛?duì)列中的排序,返回取出的數(shù)量
int drainTo(Collection c,int maxLength);//取出隊(duì)列的數(shù)據(jù),最大數(shù)量為maxLength,返回實(shí)際獲取得數(shù)量
其他隊(duì)列基本都有實(shí)現(xiàn)以下的方法:
peek()與poll()功能一樣
隊(duì)列有add()方法,其內(nèi)部實(shí)現(xiàn)與put()基本都是一樣的.而且還有許多方法與列表方法一樣用的,如size(),remove(),clear(),遍歷時(shí)使用迭代器遍歷.其中remove()為刪除隊(duì)頭
隊(duì)列的有界無界表明其是否指定或限定隊(duì)列大小

ArrayBlockingQueue

用數(shù)組實(shí)現(xiàn)的有界阻塞隊(duì)列,按照先進(jìn)先出的原則.

public class ArrayBlockingQueueTest {
    ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(5,true);//定義隊(duì)列大小為5,隊(duì)列為先進(jìn)先出順序,false為未指定順序
    ExecutorService executorService = Executors.newSingleThreadExecutor();//單線程的線程池

    public ArrayBlockingQueueTest() {
        for (int i = 0;i<6;i++){
            put("數(shù)據(jù):"+i);//放入數(shù)據(jù)
        }
    }

    public void put(String data){
        try {
            arrayBlockingQueue.put(data);//向隊(duì)列中放入數(shù)據(jù)
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        handle();//開啟線程處理
    }

    public void handle(){
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("處理中...");
                try {
                    sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                String data = null;
                try {
                    data = arrayBlockingQueue.poll(1, TimeUnit.SECONDS);//取出數(shù)據(jù),1秒內(nèi)取不出返回null
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if ( data != null) {
                    System.out.println(data+"處理結(jié)束...");
                }else {
                    System.out.println("無數(shù)據(jù)處理...");
                }
            }
        });
    }
}

LinkedBlockingQueue

基于鏈表的阻塞隊(duì)列,按照先進(jìn)先出,其加入隊(duì)列與取出隊(duì)列的線程使用獨(dú)立的鎖來控制同步,所以其有更高的并發(fā)效率,需要注意的是在初始化時(shí)如果不指定長度會默認(rèn)為無限長,這有可能會占用較多的資源,使用方法與ArrayBlockingQueue一致.

PriorityBlockingQueue

無界優(yōu)先級隊(duì)列,默認(rèn)為升序,與Arrays.sort()方法排序類似,在初始化時(shí)可以指定其初始長度,默認(rèn)為11,增長數(shù)量為當(dāng)大于等于64長度時(shí),為原長度的1.5被,當(dāng)小于64的時(shí)候?yàn)樵L度的2倍+2.初始化時(shí)可設(shè)置其排序的比較規(guī)則Comparator(),也可重寫其compareTo方法.其無法排序同優(yōu)先級


public class PriorityBlockingQueueTest {
    PriorityBlockingQueue<String> priorityBlockingQueue;
    String[] strings;

    Comparator<String> mComparator = new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return o2.length() - o1.length();
        }

        @Override
        public boolean equals(Object obj) {
            return false;
        }
    };
    public PriorityBlockingQueueTest() {
        strings = new String[]{"666", "6626", "6645457645661234566", "6612423564566", "6644564564564564564564566", "664566", "664564566", "664566"};
        priorityBlockingQueue = new PriorityBlockingQueue<>(11,mComparator);
        priorityBlockingQueue.put("666");
        priorityBlockingQueue.put("6626");
        priorityBlockingQueue.put("6645457645661234566");
        priorityBlockingQueue.put("6612423564566");
        priorityBlockingQueue.put("6644564564564564564564566");
        priorityBlockingQueue.put("664566");
        priorityBlockingQueue.put("664564566");
        priorityBlockingQueue.put("664566");

        Iterator<String> iterator = priorityBlockingQueue.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        System.out.println("-----------------------------------------");
        Arrays.sort(strings,mComparator);
        for (String data : strings){
            System.out.println(data);
        }
    }


}

運(yùn)行結(jié)果


這里寫圖片描述

經(jīng)試驗(yàn)驗(yàn)證,其內(nèi)部的排序使用二分法排序,如下代碼,結(jié)果與想象的不一樣,具體原因還有待研究

 private static <T> void siftUpUsingComparator(int k, T x, Object[] array,
                                       Comparator<? super T> cmp) {
        while (k > 0) {
            int parent = (k - 1) >>> 1;//取中間值比較
            Object e = array[parent];
            if (cmp.compare(x, (T) e) >= 0)//此處遇到返回大于等于0的就退出,退出操作有點(diǎn)問題
                break;
            array[k] = e;
            k = parent;
        }
        array[k] = x;
    }

DelayQueue

延時(shí)取出的無界隊(duì)列,基于PriorityQueue實(shí)現(xiàn)的,加入的元素需要實(shí)現(xiàn)Delayed接口,目前并不會使用

SynchronousQueue

不存儲元素的隊(duì)列,當(dāng)插入的一個(gè)元素,必須等待其他線程移除才可繼續(xù)運(yùn)行,當(dāng)移除一個(gè)元素,如使用remove且無插入在等待會報(bào)錯(cuò),使用take()會等到有元素插入了才返回,否則阻塞,其他的有就有沒有就返回null.

public class SynchronoutsQueueTest {
    SynchronousQueue<String> stringSynchronousQueue = new SynchronousQueue<>();
    public SynchronoutsQueueTest() {
        new MyThread().start();
        try {
            stringSynchronousQueue.put("666");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("----------putEndMain----------");
        try {
            System.out.println("----------poll:"+stringSynchronousQueue.take()+"Main----------");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    class MyThread extends Thread{
        @Override
        public void run() {
            try {
                sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("----------poll:"+stringSynchronousQueue.poll()+"Thread----------");
            try {
                sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                stringSynchronousQueue.put("666");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("----------putEndThread----------");
        }
    }
}

運(yùn)行結(jié)果


這里寫圖片描述

LinkedTransferQueue

無界的鏈表隊(duì)列,用于生產(chǎn)者等待消費(fèi)者的需求,其實(shí)現(xiàn)了TransferQueue接口,其中有幾個(gè)重要方法
transfer(Object o);//加入隊(duì)列,如加入時(shí)沒有取出隊(duì)列操作,會阻塞等待取出.
boolean tryTransfer(Object o);//加入隊(duì)列,如有取出的操作在等待則加入并返回true,否則不加入并返回false
boolean tryTransfer(Object o,long timeout,TimeUnit unit);//有超時(shí)機(jī)制的tryTransfer

public class LinkedTransferQueueTest {
    LinkedTransferQueue<String> linkedTransferQueue = new LinkedTransferQueue<>();
    public LinkedTransferQueueTest() {
        new TestThread().start();
        while (true) {
            try {
                Thread.sleep(3000);
                System.out.println("消費(fèi):" + linkedTransferQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    class TestThread extends Thread{
        @Override
        public void run() {
            while (true) {
                try {
                    System.out.println("出產(chǎn)...");
                    linkedTransferQueue.transfer("34636");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

運(yùn)行結(jié)果


這里寫圖片描述

在每次出產(chǎn)后都會等待消費(fèi)后再進(jìn)行下一次的出產(chǎn)

LinedBlockingDeque

雙向阻塞隊(duì)列,在初始化時(shí)可設(shè)置其最大容量,默認(rèn)為int的最大值,隊(duì)列提供了addFirst、addLast全释、offerFirst装处、offerLast、peekFirst浸船、peekLast等方法進(jìn)行對隊(duì)頭和隊(duì)尾的操作妄迁。

小結(jié)

java提供的阻塞隊(duì)列使用起來也是挺便利的,雖然有些可能寫錯(cuò)了,希望大家指出糾正.

個(gè)人博客:https://lewis-v.github.io/

公眾號
個(gè)人公眾號

</article>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市李命,隨后出現(xiàn)的幾起案子登淘,更是在濱河造成了極大的恐慌,老刑警劉巖封字,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件黔州,死亡現(xiàn)場離奇詭異,居然都是意外死亡阔籽,警方通過查閱死者的電腦和手機(jī)流妻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來笆制,“玉大人绅这,你說我怎么就攤上這事≡诹荆” “怎么了证薇?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵度苔,是天一觀的道長。 經(jīng)常有香客問我浑度,道長寇窑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任箩张,我火速辦了婚禮甩骏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘伏钠。我一直安慰自己横漏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布熟掂。 她就那樣靜靜地躺著缎浇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪赴肚。 梳的紋絲不亂的頭發(fā)上素跺,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機(jī)與錄音誉券,去河邊找鬼指厌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛踊跟,可吹牛的內(nèi)容都是我干的踩验。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼商玫,長吁一口氣:“原來是場噩夢啊……” “哼箕憾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拳昌,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤袭异,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后炬藤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體御铃,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年沈矿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了上真。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡羹膳,死狀恐怖谷羞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情溜徙,我是刑警寧澤湃缎,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站蠢壹,受9級特大地震影響嗓违,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜图贸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一蹂季、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧疏日,春花似錦偿洁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至挠阁,卻和暖如春宾肺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背侵俗。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工锨用, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人隘谣。 一個(gè)月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓增拥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子康愤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 相關(guān)文章Java并發(fā)編程(一)線程定義玷或、狀態(tài)和屬性 Java并發(fā)編程(二)同步Java并發(fā)編程(三)volatil...
    劉望舒閱讀 5,227評論 1 31
  • 1.阻塞隊(duì)列定義阻塞隊(duì)列常用于生產(chǎn)者和消費(fèi)者的場景,生產(chǎn)者是往隊(duì)列里添加元素的線程渣玲,消費(fèi)者是從隊(duì)列里拿元素的線程。...
    SDY_0656閱讀 426評論 0 1
  • 001追求 我們要么在追求的路上弟晚,要么在尋找的路上忘衍。不管怎樣都要記得:追求自己在意的,做自己想做的事情卿城。 002歲...
    思彤lu閱讀 165評論 0 2
  • 在剛成為測試人員時(shí)枚钓,不斷地提系統(tǒng)的缺陷,發(fā)現(xiàn)產(chǎn)品的問題瑟押。認(rèn)為做好測試工作搀捷,寫好用例,發(fā)現(xiàn)缺陷,提好缺陷報(bào)告就好了嫩舟,...
    安吉1987閱讀 1,273評論 0 1
  • 初遇02 平生離開了醫(yī)院氢烘,好幾天都沒有出門。只是吩咐江林每天煲著各種口味的骨頭湯家厌,往醫(yī)院送去播玖。 江林不勝其煩,嘴里...
    星如雨雨雨閱讀 248評論 0 0