首先我们了解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;
}
}