本文主要是介绍java线程(7)——阻塞队列BlockingQueue,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
回顾:
阻塞队列,英文名叫BlockingQueue。首先他是一种队列,联系之前Java基础——集合中介绍的Queue与Collection,我们就很容易开始今天的阻塞队列的学习了。来看一下他们的接口定义:
Queue:
(方法很简单,就不一一注释解释其作用了。)
public interface Queue<E> extends Collection<E> {boolean add(E e);boolean offer(E e);E remove();E poll();E element();E peek();
}
BlockingQueue:
因为是继承自Queue,方法基本类似,就不再写了。主要方法有三个:add,remove,element(用于检查)。
那到底什么是阻塞队列呢?联系前面java线程——模拟生产者与消费者的例子,在篮子中没有馒头时,生成者要放入馒头消费者才能食用;在篮子里装满馒头时,生产者就不能继续生产了,要等人去吃。阻塞队列就是生产者存放馒头的容器,消费者从中取出元素,也就是那个篮子。
public interface BlockingQueue<E> extends Queue<E> {
......}
BlockingQueue的实现类有很多,这里介绍一个很简单的ArrayBlockingQueue。他是一个数据结构组成的阻塞队列,按照FIFO先进先出的方式排序。
继续来看他的定义,下面只列举了常用的两个方法:
public class ArrayBlockingQueue<E> extends AbstractQueue<E>implements BlockingQueue<E>, java.io.Serializable {//放入元素public void put(E e) throws InterruptedException {checkNotNull(e);final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {while (count == items.length)notFull.await();enqueue(e);} finally {lock.unlock();}}//取元素public E take() throws InterruptedException {final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {while (count == 0)notEmpty.await();return dequeue();} finally {lock.unlock();}}}
来个例子:
//Capacity为3的阻塞队列final BlockingQueue queue = new ArrayBlockingQueue(3);for (int i = 0; i < 2; i++) {//1、放馒头线程new Thread() {@Overridepublic void run() {while (true) {try {Thread.sleep((long) (Math.random() * 10000));System.out.println(Thread.currentThread().getName()+ "准备放馒头!");//每次放入一个馒头queue.put(1);System.out.println(Thread.currentThread().getName()+ "已经放了馒头," + "队列目前有" + queue.size()+ "个馒头");} catch (InterruptedException e) {e.printStackTrace();}}}}.start();}//2、取馒头线程new Thread() {@Overridepublic void run() {while (true) {try {Thread.sleep((long) (Math.random() * 10000));System.out.println(Thread.currentThread().getName()+ "准备取馒头!");//拿走一个queue.take();System.out.println(Thread.currentThread().getName()+ "已经取走馒头," + "队列目前有" + queue.size() + "个馒头");} catch (InterruptedException e) {e.printStackTrace();}}}}.start();}
部分执行结果:
对比:
和之前手动实现生产者消费者的例子相比,这次的实现就简单多了。不再需要去管篮子里的“取”和“放”的操作,不用关心线程的同步互斥问题,不用关心篮子是空了还是满了。只需要简单的调用put或take方法即可,把复杂的阻塞问题教给BlockingQueue去处理,但是原理还是一样的。
这篇关于java线程(7)——阻塞队列BlockingQueue的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!