首先我們瞭解BlockingQueue的核心方法:
方法類型 | 拋出異常 | 特殊值 | 阻塞 | 超時 |
插入 | add(e) | offer(e) | put(e) | offer(e,time,unit) |
移除 | remove() | poll() | take() | poll(time,unit) |
檢查 | element() | peek() | 不可用 | 不可用 |
拋出異常 |
當阻塞隊列滿時,再往隊列裏add插入元素會拋出llegalStateException;Queue full 當阻塞隊列空時,再往隊列裏remove移除元素會拋出NoSuchElementException |
特殊值 |
插入方法:成功true 失敗false 移除方法:成功返回隊列的元素,隊列中沒有則返回null |
一直阻塞 |
當阻塞隊列滿時,生產者線程繼續往隊列裏put元素,隊列會一直阻塞生產線程直到put數據或響應中斷退出。 當阻塞隊列空時,消費者線程試圖從隊列裏take元素,隊列會一直阻塞消費者線程直到隊列可用 |
超時退出 | 當阻塞隊列滿時,隊列會阻塞生產者線程一定時間,超過時間後生產者線程會退出。 |
package com.java.thread.blockingQueue;
import org.omg.PortableServer.THREAD_POLICY_ID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
class MyResource{
public volatile boolean FLAG=true;//默認開啓,進行生產+消費
private AtomicInteger atomicInteger=new AtomicInteger();
BlockingQueue<String> blockingQueue=null;
public MyResource(BlockingQueue<String> blockingQueue){
this.blockingQueue=blockingQueue;
System.out.println(blockingQueue.getClass().getName());
}
//生產
public void myProd() throws Exception{
String data=null;
boolean retValue;
while(FLAG){
data=atomicInteger.incrementAndGet()+"";
retValue=blockingQueue.offer(data,2L, TimeUnit.SECONDS);
if(retValue){
System.out.println(Thread.currentThread().getName()+"\t"+"插入隊列"+data+"成功");
}else{
System.out.println(Thread.currentThread().getName()+"\t"+"插入隊列"+data+"失敗");
}
TimeUnit.SECONDS.sleep(1);
}
System.out.println(Thread.currentThread().getName()+"\t"+"大老闆叫停了,表示FLAG=false,生產動作結束");
}
//消費
public void myConsumer() throws Exception{
String result=null;
while(FLAG){
result=blockingQueue.poll(2L,TimeUnit.SECONDS);
if(null==result||result.equals("")){
FLAG=false;
System.out.println(Thread.currentThread().getName()+"\t"+"超過2秒鐘沒有取到蛋糕,消費退出");
System.out.println();
System.out.println();
return;
}
System.out.println(Thread.currentThread().getName()+"\t"+"消費者隊列"+result+"成功");
}
}
}
/**
* 這個是有問題的吧,假如有多個消費者,那不是有的消費者會導致沒有消息消費,導致FLAG爲false,生產者也會因此退出。
* 還有就是,萬一生產者生產的時間大於2秒呢?也會導致消費者超時。
*
* 而且有條數據會先消費後生產?---這個應該是壓入數據的時候(retValue=blockingQueue.offer(data,2L, TimeUnit.SECONDS);)和
* 輸出結果的時候有延時 (System.out.println(Thread.currentThread().getName()+"\t"+"插入隊列"+data+"成功");)
*/
public class ProdConsumer_BlockQueueDemo {
public static void main(String[] args) {
MyResource myResource=new MyResource(new ArrayBlockingQueue<String>(10));
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"\t 生產線程啓動");
try {
myResource.myProd();
System.out.println();
System.out.println();
} catch (Exception e) {
e.printStackTrace();
}
},"Prod").start();
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"\t 消費線程啓動");
try {
myResource.myConsumer();
} catch (Exception e) {
e.printStackTrace();
}
},"Consm").start();
//暫停一會兒線程
try{TimeUnit.SECONDS.sleep(5);}catch (InterruptedException e){e.printStackTrace();}
System.out.println();
System.out.println();
System.out.println();
System.out.println("5秒時間到,大老闆叫停");
myResource.FLAG=false;
}
}