• 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() {
    
    				@Override
    				public 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() {
    
    			@Override
    			public 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去处理,但是原理还是一样的。

  • 相关阅读:
    PHP操作Memcache基本函数
    sublime text 设置
    获取客户端IP地址经纬度所在城市
    php 中文转拼音首字母问题
    php分类
    php +mysql 添加 删除 修改 insert into delete update
    php+mysql 内联接 和 子查询
    mysql count max min 语句用法
    mysql 查询语句
    非常不错的MySQL优化的8条经验
  • 原文地址:https://www.cnblogs.com/saixing/p/6730215.html
Copyright © 2020-2023  润新知