Java中阻塞队列的几种实现方式

来源:互联网 发布:轰炸商务印书馆知乎 编辑:程序博客网 时间:2024/05/17 03:16

1.wait()和notify()方式(摘自:https://segmentfault.com/a/1190000000373535)

阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列。

线程1往阻塞队列中添加元素,而线程2从阻塞队列中移除元素。

具体实现:

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方法时,都不会阻塞,都能够正常的往队列中添加或者移除元素。

2.并发类实现

eg:使用ArrayBlockingQueue实现(摘自:http://blog.csdn.net/eson_15/article/details/51586127)

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:一个由链表结构组成的双向阻塞队列。
摘自:

http://ifeve.com/java-blocking-queue/

阻塞队列的适用场景:

生产者和消费者速度不一致造成的队列为空或者队列过大的情况。


原创粉丝点击