阻塞队列与普通队列的区别
阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列。
阻塞队列的使用场景
最常见的就是省产消费者模式,生产者和消费者速度不一致造成的队列为空或者队列过大的情况。
Java 阻塞队列实现方式
方法一:wait()和notify()方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public class BlockingQueue { private List queue = new LinkedList(); private int limit = 10; public BlockingQueue(int limit){ this.limit = limit; } public synchronized void enqueue(Object item) throws InterruptedException { while(this.queue.size() == this.limit) { wait(); } if(this.queue.size() == 0) { notifyAll(); } this.queue.add(item); } public synchronized Object dequeue() throws InterruptedException{ while(this.queue.size() == 0){ wait(); } if(this.queue.size() == this.limit){ notifyAll(); } return this.queue.remove(0); } } |
在enqueue和dequeue方法内部,只有队列的大小等于上限(limit)或者下限(0)时,才调用notifyAll方法。如果队列的大小既不等于上限,也不等于下限,任何线程调用enqueue或者dequeue方法时,都不会阻塞,都能够正常的往队列中添加或者移除元素。
方法二:阻塞队列类实现
使用ArrayBlockingQueue实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
public class BlockingQueueTest { public static void main(String[] args) { final BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(3); //缓冲区允许放3个数据 for(int i = 0; i < 2; i ++) { new Thread() { //开启两个线程不停的往缓冲区存数据 @Override public void run() { while(true) { try { Thread.sleep((long) (Math.random()*1000)); System.out.println(Thread.currentThread().getName() + "准备放数据" + (queue.size() == 3?"..队列已满,正在等待":"...")); queue.put(1); System.out.println(Thread.currentThread().getName() + "存入数据," + "队列目前有" + queue.size() + "个数据"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }.start(); } new Thread() { //开启一个线程不停的从缓冲区取数据 @Override public void run() { while(true) { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "准备取数据" + (queue.size() == 0?"..队列已空,正在等待":"...")); queue.take(); System.out.println(Thread.currentThread().getName() + "取出数据," + "队列目前有" + queue.size() + "个数据"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }.start(); } } |
几种常用的阻塞队列
- ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。
- LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。
- PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
- DelayQueue:一个使用优先级队列实现的无界阻塞队列。
- SynchronousQueue:一个不存储元素的阻塞队列。
- LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
- LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。
0