BlockingQueue 继承关系图:
阻塞队列的使用场景:多线程并发处理,线程池。
队列的使用操作:添加、移除
操作的4组API:
1、抛出异常
import java.util.concurrent.ArrayBlockingQueue;
/**
* 阻塞队列测试
*/
public class BlockingQueueDemo {
public static void main(String[] args) {
// 设置指定队列的大小
ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
//=============队列新增
System.out.println( blockingQueue.add( "A" ) );
System.out.println( blockingQueue.add( "B" ) );
System.out.println( blockingQueue.add( "C" ) );
//java.lang.IllegalStateException: Queue full 抛出异常
//System.out.println( blockingQueue.add( "D" ) );
//=============队列移除
System.out.println( blockingQueue.remove() );
System.out.println( blockingQueue.remove() );
System.out.println( blockingQueue.remove() );
//java.util.NoSuchElementException 抛出异常
System.out.println( blockingQueue.remove() );
}
}
如上述代码,在我们add与remove操作中,数据添加超过队列大小或者队列里面没有数据时均会抛出异常。
2、有返回值,不抛出异常
import java.util.concurrent.ArrayBlockingQueue;
/**
* 阻塞队列测试
*/
public class BlockingQueueDemo {
public static void main(String[] args) {
// 设置队列的大小
ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
//=============队列offer
System.out.println( blockingQueue.offer( "A" ) );
System.out.println( blockingQueue.offer( "B" ) );
System.out.println( blockingQueue.offer( "C" ) );
//返回false
System.out.println( blockingQueue.offer( "D" ) );
//=============队列poll
System.out.println( blockingQueue.poll() );
System.out.println( blockingQueue.poll() );
System.out.println( blockingQueue.poll() );
//结果返回null
System.out.println( blockingQueue.poll() );
}
}
如上述代码,在我们add与remove操作中,数据添加超过队列大小时会返回flase,队列为空时进行poll结果会返回null;
3、 阻塞,等待
import java.util.concurrent.ArrayBlockingQueue;
/**
* 阻塞队列测试
*/
public class BlockingQueueDemo {
public static void main(String[] args) throws InterruptedException {
// 设置队列的大小
ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
//=============队列put
blockingQueue.put( "A" ) ;
blockingQueue.put( "B" ) ;
blockingQueue.put( "C" ) ;
//返回false
// blockingQueue.put( "D" ) ;
//=============队列take
System.out.println( blockingQueue.take() );
System.out.println( blockingQueue.take() );
System.out.println( blockingQueue.take() );
//这里会阻塞,知道有数据
System.out.println( blockingQueue.take() );
}
}
如上述代码,在我们put与take操作中,数据添加超过队列大小时会一直阻塞直到能够put成功后再结束,当队列为空时进行poll一直会阻塞到队列里面有值才结束;
通过源码我们可以看到,阻塞队列是通过lock锁与Condition进行线程间的通讯去实现的;
4、超时等待
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* 阻塞队列测试
*/
public class BlockingQueueDemo {
public static void main(String[] args) throws InterruptedException {
// 设置队列的大小
ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
//=============队列新增
blockingQueue.offer( "A" ,2 , TimeUnit.SECONDS) ;
blockingQueue.offer( "B" ,2 , TimeUnit.SECONDS) ;
blockingQueue.offer( "C" ,2 , TimeUnit.SECONDS) ;
//等待2秒没有队列没有空闲位置结束offer
blockingQueue.offer( "D" ,2 , TimeUnit.SECONDS) ;
//=============队列移除
System.out.println( blockingQueue.poll(2,TimeUnit.SECONDS));
System.out.println( blockingQueue.poll(2,TimeUnit.SECONDS));
System.out.println( blockingQueue.poll(2,TimeUnit.SECONDS));
//等待2秒没数据停止poll
System.out.println( blockingQueue.poll(2,TimeUnit.SECONDS));
}
}
不管是offer还是poll,在指定的时间内没有队列中没有空闲大小或者没有数据时,会停止当前操作,运行其他任务等。
通过源码我们可以看到,也是用到了Condition类中的awaitNanos方法。