队列主要遵循先进先出,后进后出的原则。
阻塞式队列与非阻塞式队列
区别:
**阻塞式队列:**入列时如果超出队列总数,会等待(阻塞)。出列时如果获取队列为空,也会等待(阻塞)。效率低。能够防止队列容器溢出,防止丢失数据。
**非阻塞式队列:**入列时如果超出队列总数直接报错。效率高。
并发队列-ConcurrentLinkedQueue(非阻塞式队列)
ConcurrentLinkedQueue是无界队列。
ConcurrentLinkedQeque queue = new ConcurrentLinkedQeque();
queue .offer("Lucy");
queue .offer("Jimmy");
queue .offer("James");
//从头获取元素,删除该元素
System.out.println(queue .poll());
//从头获取元素,不刪除该元素
System.out.println(queue .peek());
//获取总长度
System.out.println(queue .size());
BlockingQueue(阻塞式队列)
ArrayBlockingQueue
ArrayBlockingQueue是一个有边界的阻塞队列,它的内部实现是一个数组。有边界的意思是它的容量是有限的,我们必须在其初始化的时候指定它的容量大小,容量大小一旦指定就不可改变。
<String> arrays = new ArrayBlockingQueue<String>(3);
arrays.add("李四");//添加非阻塞式队列
arrays.add("王五");
arrays.add("李四");
// 添加阻塞队列
arrays.offer("张三", 3, TimeUnit.SECONDS);//添加阻塞式队列,等待3秒
LinkedBlockingQueue
LinkedBlockingQueue阻塞队列大小的配置是可选的,如果我们初始化时指定一个大小,它就是有边界的,如果不指定,它就是无边界的。说是无边界,其实是采用了默认大小为Integer.MAX_VALUE的容量 。它的内部实现是一个链表。
PriorityBlockingQueue
PriorityBlockingQueue是一个没有边界的队列,它的排序规则和 java.util.PriorityQueue一样。需要注
意,PriorityBlockingQueue中允许插入null对象。
所有插入PriorityBlockingQueue的对象必须实现 java.lang.Comparable接口,队列优先级的排序规则就 是按照我们对这个接口的实现来定义的。
另外,我们可以从PriorityBlockingQueue获得一个迭代器Iterator,但这个迭代器并不保证按照优先级顺 序进行迭代。
SynchronousQueue
SynchronousQueue队列内部仅允许容纳一个元素。当一个线程插入一个元素后会被阻塞,除非这个元素被另一个线程消费。
模拟生产者/消费者
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 生产者
*/
class ProduderThread implements Runnable{
private BlockingQueue<String> blockingQueue;
private AtomicInteger count = new AtomicInteger();
private volatile boolean FLAG = true;
public ProduderThread(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
System.out.println("生成者启动...");
while (FLAG){
String data = count.incrementAndGet() + "";
try {
boolean res = blockingQueue.offer(data,2,TimeUnit.SECONDS);
if(res){
System.out.println(Thread.currentThread().getName()+"生产队列"+data+"成功");
}else{
System.out.println(Thread.currentThread().getName()+"生产队列"+data+"失败");
}
Thread.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
}
}
public void stop(){
FLAG = false;
}
}
/**
* 消费者
*/
class ConsumerThread implements Runnable{
private BlockingQueue<String> blockingQueue;
private volatile boolean FLAG = true;
public ConsumerThread(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
System.out.println("消费者启动...");
while (FLAG){
try {
String data = blockingQueue.poll(2,TimeUnit.SECONDS);
if(data == null){
FLAG = false;
System.out.println(Thread.currentThread().getName()+"消费者获取数据超时");
return;
}
System.out.println(Thread.currentThread().getName()+"消费者获取数据成功,data:"+data);
}catch (Exception e){
e.printStackTrace();
}
}
}
public void stop(){
FLAG = false;
}
}
public class BlockingQueueTest {
public static void main(String[] args) {
BlockingQueue<String> blockingQueue = new LinkedBlockingQueue(3);
ProduderThread produderThread = new ProduderThread(blockingQueue);
new Thread(produderThread).start();
new Thread(new ConsumerThread(blockingQueue)).start();
try{
Thread.sleep(20*1000);
produderThread.stop();
}catch (Exception e){
e.printStackTrace();
}
}
}