java多線程隊列
A. java多線程共同操作同一個隊列,怎麼實現
具體代碼如下:
B. Java多線程是什麼意思
Java多線程實現方式主要有三種:繼承Thread類、實現Runnable介面、使用ExecutorService、Callable、Future實現有返回結果的多線程。其中前兩種方式線程執行完後都沒有返回值,只有最後一種是帶返回值的。
1、繼承Thread類實現多線程
繼承Thread類的方法盡管被我列為一種多線程實現方式,但Thread本質上也是實現了Runnable介面的一個實例,它代表一個線程的實例,並且,啟動線程的唯一方法就是通過Thread類的start()實例方法。start()方法是一個native方法,它將啟動一個新線程,並執行run()方法。這種方式實現多線程很簡單,通過自己的類直接extend Thread,並復寫run()方法,就可以啟動新線程並執行自己定義的run()方法。例如:
代碼說明:
上述代碼中Executors類,提供了一系列工廠方法用於創先線程池,返回的線程池都實現了ExecutorService介面。
public static ExecutorService newFixedThreadPool(int nThreads)
創建固定數目線程的線程池。
public static ExecutorService newCachedThreadPool()
創建一個可緩存的線程池,調用execute 將重用以前構造的線程(如果線程可用)。如果現有線程沒有可用的,則創建一個新線程並添加到池中。終止並從緩存中移除那些已有 60 秒鍾未被使用的線程。
public static ExecutorService newSingleThreadExecutor()
創建一個單線程化的Executor。
public static ScheledExecutorService newScheledThreadPool(int corePoolSize)
創建一個支持定時及周期性的任務執行的線程池,多數情況下可用來替代Timer類。
總結:ExecutoreService提供了submit()方法,傳遞一個Callable,或Runnable,返回Future。如果Executor後台線程池還沒有完成Callable的計算,這調用返回Future對象的get()方法,會阻塞直到計算完成。
C. 鍦↗ava 涓澶氱嚎紼嬬殑瀹炵幇鏂規硶鏈夊摢浜涳紝濡備綍浣跨敤鍀烇綖鍀烇綖鍀烇綖鍀烇綖鍀烇綖鍀烇綖鍀烇綖鍀烇綖鍀烇綖鎬
1銆 璁よ瘑Thread鍜孯unnable
Java涓瀹炵幇澶氱嚎紼嬫湁涓ょ嶉斿緞錛氱戶鎵縏hread綾繪垨鑰呭疄鐜癛unnable鎺ュ彛銆俁unnable鏄鎺ュ彛錛屽緩璁鐢ㄦ帴鍙g殑鏂瑰紡鐢熸垚綰跨▼錛屽洜涓烘帴鍙e彲浠ュ疄鐜板氱戶鎵匡紝鍐典笖Runnable鍙鏈変竴涓猺un鏂規硶錛屽緢閫傚悎緇ф壙銆傚湪浣跨敤Thread鐨勬椂鍊欏彧闇緇ф壙Thread錛屽苟涓攏ew涓涓瀹炰緥鍑烘潵錛岃皟鐢╯tart()鏂規硶鍗沖彲浠ュ惎鍔ㄤ竴涓綰跨▼銆
Thread Test = new Thread();
Test.start();
鍦ㄤ嬌鐢≧unnable鐨勬椂鍊欓渶瑕佸厛new涓涓瀹炵幇Runnable鐨勫疄渚嬶紝涔嬪悗鍚鍔═hread鍗沖彲銆
Test impelements Runnable;
Test t = new Test();
Thread test = new Thread(t);
test.start();
鎬葷粨錛歍hread鍜孯unnable鏄瀹炵幇java澶氱嚎紼嬬殑2縐嶆柟寮忥紝runable鏄鎺ュ彛錛宼hread鏄綾伙紝寤鴻浣跨敤runable瀹炵幇java澶氱嚎紼嬶紝涓嶇″備綍錛屾渶緇堥兘闇瑕侀氳繃thread.start()鏉ヤ嬌綰跨▼澶勪簬鍙榪愯岀姸鎬併
2銆 璁よ瘑Thread鐨剆tart鍜宺un
1錛 start錛
鐢╯tart鏂規硶鏉ュ惎鍔ㄧ嚎紼嬶紝鐪熸e疄鐜頒簡澶氱嚎紼嬭繍琛岋紝榪欐椂鏃犻渶絳夊緟run鏂規硶浣撲唬鐮佹墽琛屽畬姣曡岀洿鎺ョ戶緇鎵ц屼笅闈㈢殑浠g爜銆傞氳繃璋冪敤Thread綾葷殑start()鏂規硶鏉ュ惎鍔ㄤ竴涓綰跨▼錛岃繖鏃舵ょ嚎紼嬪勪簬灝辯華錛堝彲榪愯岋級鐘舵侊紝騫舵病鏈夎繍琛岋紝涓鏃﹀緱鍒皊pu鏃墮棿鐗囷紝灝卞紑濮嬫墽琛宺un()鏂規硶錛岃繖閲屾柟娉時un()縐頒負綰跨▼浣擄紝瀹冨寘鍚浜嗚佹墽琛岀殑榪欎釜綰跨▼鐨勫唴瀹癸紝Run鏂規硶榪愯岀粨鏉燂紝姝ょ嚎紼嬮殢鍗崇粓姝銆
2錛 run錛
run()鏂規硶鍙鏄綾葷殑涓涓鏅閫氭柟娉曡屽凡錛屽傛灉鐩存帴璋冪敤Run鏂規硶錛岀▼搴忎腑渚濈劧鍙鏈変富綰跨▼榪欎竴涓綰跨▼錛屽叾紼嬪簭鎵ц岃礬寰勮繕鏄鍙鏈変竴鏉★紝榪樻槸瑕侀『搴忔墽琛岋紝榪樻槸瑕佺瓑寰卹un鏂規硶浣撴墽琛屽畬姣曞悗鎵嶅彲緇х畫鎵ц屼笅闈㈢殑浠g爜錛岃繖鏍峰氨娌℃湁杈懼埌鍐欑嚎紼嬬殑鐩鐨勩
鎬葷粨錛氳皟鐢╯tart鏂規硶鏂瑰彲鍚鍔ㄧ嚎紼嬶紝鑰宺un鏂規硶鍙鏄痶hread鐨勪竴涓鏅閫氭柟娉曡皟鐢錛岃繕鏄鍦ㄤ富綰跨▼閲屾墽琛屻
3銆 綰跨▼鐘舵佽存槑
綰跨▼鐘舵佷粠澶х殑鏂歸潰鏉ヨ達紝鍙褰掔粨涓猴細鍒濆嬬姸鎬併佸彲榪愯岀姸鎬併佷笉鍙榪愯岀姸鎬佸拰娑堜骸鐘舵侊紝鍏蜂綋鍙緇嗗垎涓轟笂鍥炬墍紺7涓鐘舵侊紝璇存槑濡備笅錛
1錛 綰跨▼鐨勫疄鐜版湁涓ょ嶆柟寮忥紝涓鏄緇ф壙Thread綾伙紝浜屾槸瀹炵幇Runnable鎺ュ彛錛屼絾涓嶇℃庢牱錛屽綋鎴戜滑new浜唗hread瀹炰緥鍚庯紝綰跨▼灝辮繘鍏ヤ簡鍒濆嬬姸鎬侊紱
2錛 褰撹ュ硅薄璋冪敤浜唖tart()鏂規硶錛屽氨榪涘叆鍙榪愯岀姸鎬侊紱
3錛 榪涘叆鍙榪愯岀姸鎬佸悗錛屽綋璇ュ硅薄琚鎿嶄綔緋葷粺閫変腑錛岃幏寰桟PU鏃墮棿鐗囧氨浼氳繘鍏ヨ繍琛岀姸鎬侊紱
4錛 榪涘叆榪愯岀姸鎬佸悗case灝辨瘮杈冨氾紝澶ц嚧鏈夊備笅鎯呭艦錛
路run()鏂規硶鎴杕ain()鏂規硶緇撴潫鍚庯紝綰跨▼灝辮繘鍏ョ粓姝㈢姸鎬侊紱
路褰撶嚎紼嬭皟鐢ㄤ簡鑷韜鐨剆leep()鏂規硶鎴栧叾浠栫嚎紼嬬殑join()鏂規硶錛屽氨浼氳繘鍏ラ樆濉炵姸鎬(璇ョ姸鎬佹棦鍋滄㈠綋鍓嶇嚎紼嬶紝浣嗗苟涓嶉噴鏀炬墍鍗犳湁鐨勮祫婧)銆傚綋sleep()緇撴潫鎴杍oin()緇撴潫鍚庯紝璇ョ嚎紼嬭繘鍏ュ彲榪愯岀姸鎬侊紝緇х畫絳夊緟OS鍒嗛厤鏃墮棿鐗囷紱
路褰撶嚎紼嬪垰榪涘叆鍙榪愯岀姸鎬(娉ㄦ剰錛岃繕娌¤繍琛)錛屽彂鐜板皢瑕佽皟鐢ㄧ殑璧勬簮琚閿佺墷(synchroniza,lock)錛屽皢浼氱珛鍗寵繘鍏ラ攣奼犵姸鎬侊紝絳夊緟鑾峰彇閿佹爣璁(榪欐椂鐨勯攣奼犻噷涔熻稿凡緇忔湁浜嗗叾浠栫嚎紼嬪湪絳夊緟鑾峰彇閿佹爣璁幫紝榪欐椂瀹冧滑澶勪簬闃熷垪鐘舵侊紝鏃㈠厛鍒板厛寰)錛屼竴鏃︾嚎紼嬭幏寰楅攣鏍囪板悗錛屽氨杞鍏ュ彲榪愯岀姸鎬侊紝絳夊緟OS鍒嗛厤CPU鏃墮棿鐗囷紱
路褰撶嚎紼嬭皟鐢╳ait()鏂規硶鍚庝細榪涘叆絳夊緟闃熷垪(榪涘叆榪欎釜鐘舵佷細閲婃斁鎵鍗犳湁鐨勬墍鏈夎祫婧愶紝涓庨樆濉炵姸鎬佷笉鍚)錛岃繘鍏ヨ繖涓鐘舵佸悗錛屾槸涓嶈兘鑷鍔ㄥ敜閱掔殑錛屽繀欏諱緷闈犲叾浠栫嚎紼嬭皟鐢╪otify()鎴杗otifyAll()鏂規硶鎵嶈兘琚鍞ら啋(鐢變簬notify()鍙鏄鍞ら啋涓涓綰跨▼錛屼絾鎴戜滑鐢變笉鑳界『瀹氬叿浣撳敜閱掔殑鏄鍝涓涓綰跨▼錛屼篃璁告垜浠闇瑕佸敜閱掔殑綰跨▼涓嶈兘澶熻鍞ら啋錛屽洜姝ゅ湪瀹為檯浣跨敤鏃訛紝涓鑸閮界敤notifyAll()鏂規硶錛屽敜閱掓湁鎵綰跨▼)錛岀嚎紼嬭鍞ら啋鍚庝細榪涘叆閿佹睜錛岀瓑寰呰幏鍙栭攣鏍囪般
路褰撶嚎紼嬭皟鐢╯top鏂規硶錛屽嵆鍙浣跨嚎紼嬭繘鍏ユ秷浜$姸鎬侊紝浣嗘槸鐢變簬stop鏂規硶鏄涓嶅畨鍏ㄧ殑錛屼笉榧撳姳浣跨敤錛屽ぇ瀹跺彲浠ラ氳繃run鏂規硶閲岀殑鏉′歡鍙橀氬疄鐜扮嚎紼嬬殑stop銆
D. 璇劇▼璁捐¢樼洰錛屽氱嚎紼嬬紪紼嬶細鍖婚櫌闂ㄨ瘖妯℃嫙錛屾兂鐢╦ava瀹炵幇錛屾眰澶х炴寚鐐
鍏稿瀷鐨勭敓浜ц呮秷璐硅呮ā鍨嬨
浜嗚Вj5鐨勫苟鍙戝簱錛岄偅涓騫跺彂搴撲腑鏈夐傚悎緇勪歡瀹炵幇銆
濡傛灉涓嶄簡瑙o紝榪欎箞鏉ワ細
鍒涘緩涓涓闃熷垪錛屾ら槦鍒楄佹眰綰跨▼瀹夊叏錛屽傛灉闃熷垪涓虹┖鍒欐秷璐硅呴樆濉炪傚傛灉闃熷垪杈懼埌鏌愪釜鏈澶у礆紝鍒欓樆濉炵敓浜ц呫
闃熷垪鐢錛屾櫘閫氱殑list鎴栧疄鐜板ソ鐨勯槦鍒楀寘瑁呮垚綰跨▼瀹夊叏鐨勩
鐢╯ynchronized鍚屾ュ師鏂規硶鎴栦唬鐮佸潡銆
鍐欎竴涓鎴杗涓綰跨▼錛屾ā鎷熺棶浜猴紝鎺掗槦鍔炵悊涓氬姟錛屽線涓婇潰鐨勯槦鍒椾腑娣誨姞鏁版嵁銆
褰撹揪鍒伴槦鍒楃殑鏈澶у圭Н錛岄樆濉烇紝絳夊緟鐢熶駭鑰呯嚎紼嬪彇鏁版嵁銆
闃誨烇細makerLock.wait();//鉶氭嫙鏈轟細鍑鴻╃嚎紼嬫寕璧鳳紝鍏跺疄灝辨槸鎿嶄綔緋葷粺錛屼繚瀛樺綋鍓嶇嚎紼嬪湪cpu涓婄殑榪愯岀姸鎬併傚啀鍑鴻╃嚎紼嬫e湪浣跨敤鐨刢pu璧勬簮錛屽崰鐢ㄧ殑鍐呭瓨涓嶄細閲婃斁銆
寰闃熷垪鎻掑叆鏁版嵁鐨勬椂鍊欙紝鍥犱負涓嶇煡閬撴槸鍚︽湁娑堣垂鑰呭勪簬絳夊緟鐘舵侊紝閫氱煡娑堣垂鑰咃細
customerLock.notifyAll();//鉶氭嫙鏈鴻皟搴︽秷璐硅呯嚎紼嬭繍琛岋紝瀹為檯涓婃槸鎿嶄綔緋葷粺錛屾妸淇濆瓨鐨勬秷璐硅呯嚎紼嬬姸鎬侊紝浠庢柊鍔犺澆鍒癱pu涓鎺ョ潃榪愯屻傛帴鐫榪愯岀嚎紼嬫槸浠繪剰鐨勶紝鍙栧喅浜庝笉鍚屾搷浣滅郴緇熺殑綰跨▼璋冨害綆楁硶銆
娑堣垂鑰呯嚎紼嬭誨彇涓涓鏁版嵁鍚庯紝瑕侀氱煡鐢熶駭鑰咃紝鍙浠ョ戶緇錛岄亾鐞嗗悓涓婏細
makerLock.notifyAll();
闃熷垪涓錛屾棤鏁版嵁鍙璇葷殑鏃跺欙細
customerLock.wait();//鍘熺悊鍚屼笂錛
鏈鍚庢敞鎰忥紝鐢熶駭鑰呰窡娑堣垂鑰呬嬌鐢ㄤ簡涓や釜涓嶅悓鐨勫硅薄閿併俵ock.wait()鐨勪嬌鐢ㄦ柟娉曟槸榪欐牱鐨勶細
synchronized(lock){
......
while(condition==true){
lock.wait();
}
......
Objecto=queen.pop();
lock.notifyAll();
}
鏈鍚庡惎鍔╪涓綰跨▼璇婚槦鍒楋紝妯℃嫙鍔炵悊涓氬姟鐨勭獥鍙o紱n涓綰跨▼鍐欓槦鍒楋紝妯℃嫙鐥呬漢鎺掗槦銆
鏂扮嚎紼嬪簱涔熸湁璺熻佺嚎紼嬪簱瀵瑰簲鐨勬柟娉曪紝鏂扮嚎紼嬪簱鏈夌嚎紼嬪畨鍏ㄧ殑楂樻晥闃熷垪銆傛病鏈変笂闈㈤夯鐑︼紝浣嗕笂闈㈠啓鐨勬槸鐞嗚В鏂扮嚎紼嬫暟鎹緇撴瀯涓庡疄鐜扮殑鍩虹銆
packagecom.;
importjava.util.LinkedList;
importjava.util.List;
importjava.util.Random;
publicclassTestThread2{
//緙撳啿涓婇檺
privatelongbufsize;
//緙撳啿
privateList<String>buf;
publicTestThread2(){
bufsize=5;
buf=newLinkedList<String>();
}
//鐢熶駭鑰呰皟鐢
publicvoidput(Strings){
//妯℃嫙鐢熶駭鑰呰窡涓嶄笂娑堣垂鑰
/*
try{
Thread.sleep(100);
}catch(InterruptedExceptione){
}
*/
synchronized(this){
//瓚呰繃闃熷垪闄愬埗灝辯瓑寰
while(buf.size()==bufsize){
System.out.println("闃熷垪宸叉弧錛岀敓浜ц:"+Thread.currentThread().getId()+"寮濮嬬瓑寰呫");
try{
this.wait();
}catch(InterruptedExceptione){
}
}
buf.add(s);
//閫氱煡娑堣垂鑰
this.notifyAll();
}
}
//娑堣垂鑰呰皟鐢
synchronizedpublicStringtake(){
//妯℃嫙娑堣垂鑰呰窡涓嶄笂鐢熶駭鑰
try{
Thread.sleep(100);
}catch(InterruptedExceptione){
}
Strings=null;
synchronized(this){
while(buf.size()==0){
System.out.println("闃熷垪涓虹┖錛屾秷璐硅:"+Thread.currentThread().getId()+"寮濮嬬瓑寰呫");
try{
this.wait();
}catch(InterruptedExceptione){
}
}
//鍙栧厛鏀懼叆鐨勫厓緔狅紝騫剁Щ闄
s=buf.get(0);
buf.remove(0);
//閫氱煡鐢熶駭鑰
this.notifyAll();
}
returns;
}
publicstaticvoidmain(String[]args){
//鑷宸卞疄鐜扮殑錛屽畨鍏ㄩ槦鍒
finalTestThread2tt=newTestThread2();
//鐢熶駭鑰
Threadp=newThread(newRunnable(){
@Override
publicvoidrun(){
while(!Thread.currentThread().isInterrupted()){
Randomr=newRandom();
tt.put(String.valueOf(r.nextInt(10)));
}
}
});
//娑堣垂鑰
Threadc1=newThread(newRunnable(){
@Override
publicvoidrun(){
while(!Thread.currentThread().isInterrupted()){
System.out.println("綰跨▼錛"+Thread.currentThread().getId()+"鑾峰彇鍒版暟鎹"+tt.take());
}
}
});
Threadc2=newThread(newRunnable(){
@Override
publicvoidrun(){
while(!Thread.currentThread().isInterrupted()){
System.out.println("綰跨▼錛"+Thread.currentThread().getId()+"鑾峰彇鍒版暟鎹"+tt.take());
}
}
});
p.start();
c1.start();
c2.start();
try{
p.join();
c1.join();
c2.join();
}catch(InterruptedExceptione){
}
}
}
E. 多線程的java 程序如何編寫
Java 給多線程編程提供了內置的支持。 一條線程指的是進程中一個單一順序的控制流,一個進程中可以並發多個線程,每條線程並行執行不同的任務。
F. java線程組,線程池,線程隊列分別是什麼有什麼區別
你好,我可以給你詳細解釋一下:
線程組表示一個線程的集合。此外,線程組也可以包含其他線程組。線程組構成一棵樹,在樹中,除了初始線程組外,每個線程組都有一個父線程組。
允許線程訪問有關自己的線程組的信息,但是不允許它訪問有關其線程組的父線程組或其他任何線程組的信息。
線程池:我們可以把並發執行的任務傳遞給一個線程池,來替代為每個並發執行的任務都啟動一個新的線程。只要池裡有空閑的線程,任務就會分配給一個線程執行。在線程池的內部,任務被插入一個阻塞隊列(Blocking Queue ),線程池裡的線程會去取這個隊列里的任務。當一個新任務插入隊列時,一個空閑線程就會成功的從隊列中取出任務並且執行它。
線程池經常應用在多線程伺服器上。每個通過網路到達伺服器的連接都被包裝成一個任務並且傳遞給線程池。線程池的線程會並發的處理連接上的請求。以後會再深入有關 Java 實現多線程伺服器的細節。
線程隊列:是指線程處於擁塞的時候形成的調度隊列
排隊有三種通用策略:
直接提交。工作隊列的默認選項是 SynchronousQueue,它將任務直接提交給線程而不保持它們。在此,如果不存在可用於立即運行任務的線程,則試圖把任務加入隊列將失敗,因此會構造一個新的線程。此策略可以避免在處理可能具有內部依賴性的請求集時出現鎖。直接提交通常要求無界 maximumPoolSizes 以避免拒絕新提交的任務。當命令以超過隊列所能處理的平均數連續到達時,此策略允許無界線程具有增長的可能性。
無界隊列。使用無界隊列(例如,不具有預定義容量的 LinkedBlockingQueue)將導致在所有corePoolSize 線程都忙時新任務在隊列中等待。這樣,創建的線程就不會超過 corePoolSize。(因此,maximumPoolSize的值也就無效了。)當每個任務完全獨立於其他任務,即任務執行互不影響時,適合於使用無界隊列;例如,在 Web頁伺服器中。這種排隊可用於處理瞬態突發請求,當命令以超過隊列所能處理的平均數連續到達時,此策略允許無界線程具有增長的可能性。
有界隊列。當使用有限的 maximumPoolSizes時,有界隊列(如 ArrayBlockingQueue)有助於防止資源耗盡,但是可能較難調整和控制。隊列大小和最大池大小可能需要相互折衷:使用大型隊列和小型池可以最大限度地降低 CPU 使用率、操作系統資源和上下文切換開銷,但是可能導致人工降低吞吐量。如果任務頻繁阻塞(例如,如果它們是 I/O邊界),則系統可能為超過您許可的更多線程安排時間。使用小型隊列通常要求較大的池大小,CPU使用率較高,但是可能遇到不可接受的調度開銷,這樣也會降低吞吐量。
G. 線程池-參數篇:2.隊列
多線程環境中,通過隊列可以很容易實現線程間數據共享,比如經典的「生產者」和「消費者」模型中,通過隊列可以很便利地實現兩者之間的數據共享;同時作為BlockingQueue的使用者,我們不需要關心什麼時候需要阻塞線程,什麼時候需要喚醒線程,因為這一切BlockingQueue的實現者都給一手包辦了。
基於數組的阻塞隊列實現,在ArrayBlockingQueue內部,維護了一個定長數組,以便緩存隊列中的數據對象,另外還保存著兩個整形變數,分別標識著隊列的頭部和尾部在數組中的位置。
ArrayBlockingQueue在生產者放入數據和消費者獲取數據,都是共用同一個鎖對象,由此也意味著兩者無法真正並行運行,而在創建ArrayBlockingQueue時,我們還可以控制對象的內部鎖是否採用公平鎖,默認採用非公平鎖。
按照實現原理來分析,ArrayBlockingQueue完全可以採用分離鎖,從而實現生產者和消費者操作的完全並行運行。
基於鏈表的阻塞隊列,其內部也維持著一個數據緩沖隊列(由一個鏈表構成),當生產者往隊列中放入一個數據時,隊列會從生產者手中獲取數據,並緩存在隊列內部,而生產者立即返回;只有當隊列緩沖區達到最大值緩存容量時(LinkedBlockingQueue可以通過構造函數指定該值),才會阻塞生產者隊列,直到消費者從隊列中消費掉一份數據,生產者線程會被喚醒,反之對於消費者這端的處理也基於同樣的原理。
對於生產者端和消費者端分別採用了獨立的鎖來控制數據同步,這也意味著在高並發的情況下生產者和消費者可以並行地操作隊列中的數據,以此來提高整個隊列的並發性能。
ArrayBlockingQueue和LinkedBlockingQueue間還有一個明顯的不同之處在於,前者在插入或刪除元素時不會產生或銷毀任何額外的對象實例,而後者則會生成一個額外的Node對象。這在長時間內需要高效並發地處理大批量數據的系統中,其對於GC的影響還是存在一定的區別。如果沒有指定其容量大小,LinkedBlockingQueue會默認一個類似無限大小的容量(Integer.MAX_VALUE),這樣的話,如果生產者的速度一旦大於罩伍消費者的速度,也許還沒有等到隊列滿阻塞產生,系統內存就有可能已被消耗殆盡了。
ArrayBlockingQueue和LinkedBlockingQueue是兩個最普通也是最常用的阻塞隊列,一般情況下,在處理多線程間的生產者消費者問題,使用這兩個類足以。
DelayQueue中的元素只有當其指定的延遲時間到了,才能夠從隊列中獲取到該元素。DelayQueue是一個沒有大小限制的隊列,因此往隊列中插入數據的操作(生產者)永遠不會被阻塞,而只有獲取數據的操作(消費者)才會被阻塞。
DelayQueue用於放置實現了Delayed介面的對象,其中的對象只能在其到期時才能從隊列中取走。這種隊列是有序的,即隊頭對象的延遲到期時間最長。注意:不能將null元素放置到這種隊列中。
Delayed 是一種混合風格的介面,用來標記那些應該在給定延遲時間之後執行的對象。Delayed擴展了Comparable介面,比較的基準為延時的時間值,Delayed介面的實現類getDelay的返回值應為固定宴悶沖值(final)。DelayQueue內部是使用PriorityQueue實現的。
考慮以下場景:
一種笨笨的辦法就是,使用一個後台線程,遍歷所有對象,挨個檢查。這種笨笨的辦法簡單好用,但是對象數量過多時,可能存在性能問題,檢查間隔時間不好設置,間隔時間過大,影響精確度,多小則存在效率問題。而且做不到按超時的時間順序處理。
這場景,使用DelayQueue最適合了,詳情查看 DelayedQueue學習筆記 ; 精巧好用的DelayQueue
基於優先順序的阻塞隊列(優先順序的判斷通過構造函數傳入的Compator對象來決定),需要注意PriorityBlockingQueue並不會阻塞數據生產者晌殲,而只會在沒有可消費的數據時,阻塞數據的消費者。
使用時,若生產者生產數據的速度快於消費者消費數據的速度,隨著長時間的運行,可能會耗盡所有的可用堆內存空間。在實現PriorityBlockingQueue時,內部控制線程同步的鎖採用的是公平鎖。
SynchronousQueue是一個內部只能包含零個元素的隊列。插入元素到隊列的線程被阻塞,直到另一個線程從隊列中獲取元素。同樣,如果線程嘗試獲取元素並且當前沒有線程在插入元素,則該線程將被阻塞,直到有線程將元素插入隊列
聲明一個SynchronousQueue有公平模式和非公平模式,區別如下:
參考: Java多線程-工具篇-BlockingQueue
12. SynchronousQueue