16_Queue_利用wait()和notify()编写一个阻塞队列
【线程间通信概念】
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就成为整体必用方式之一。当线程存在通信指挥,线程间的交互性会更强大,在提高CPU利用率的同时还会使开发人员对线程任务的处理过程中进行有效的把控和监督。
【使用wait和notify的注意点】
1.wait和notify必须配合synchronized关键字使用
2.wait方法释放锁,而notify不会释放锁
【BlockingQueue】
阻塞队列,支持阻塞的机制,阻塞地放入和得到数据。我们来自行实现LinkedBlockingQueue下面的两个简单的方法put()和take()。
[ put ]
把一个Object加到BlockingQueue里,如果BlockingQueue没有空间,则调用此方法的线程被阻塞,直到BlockingQueue里面有空间再继续。
[ take ]
取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的数据被加入。
【例子】
package com.higgin.part7; import java.util.LinkedList; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class MyQueue { //1.需要一个承装元素的队列 private LinkedList<Object> list = new LinkedList<>(); //2.计数器 private AtomicInteger count = new AtomicInteger(0); //3.队列的上限和下限 private final int maxSize; private final int minSize = 0; //4.构造方法 public MyQueue(int size){ this.maxSize = size; } //5.锁 private final Object lock = new Object(); /** * 把一个对象obj添加到BlockingQueue中 * 如果BlockingQueue没有空间,则调用此方法的线程被阻断,直到BolckingQueue里面有空间 */ public void put(Object obj){ synchronized(lock){ while(count.get() == this.maxSize){ try{ lock.wait(); }catch(InterruptedException e){ e.printStackTrace(); } } //1.加入元素 list.add(obj); //2.累加计数器 count.incrementAndGet(); //3.此时BlockingQueue中已经有元素,可以执行take方法,所以去唤醒take()方法 lock.notify(); System.out.println("新加入的元素为:"+obj); } } /** * 取走BlockingQueue里排在首位的对象 * 若BlockingQueue为空,进入阻塞状态 */ public Object take(){ Object ret =null; synchronized(lock){ while(count.get() == this.minSize){ try{ lock.wait(); }catch(InterruptedException e){ e.printStackTrace(); } } //1. 移除排在首位的元素 ret = list.removeFirst(); //2.计数器递减 count.decrementAndGet(); //3.唤醒另外一个线程 lock.notify(); } return ret; } public int getSize(){ return this.count.get(); } public static void main(String[] args){ final MyQueue myQueue = new MyQueue(5); myQueue.put("AAA"); myQueue.put("BBB"); myQueue.put("CCC"); myQueue.put("DDD"); myQueue.put("EEE"); System.out.println("当前容器的长度:" + myQueue.getSize()); Thread t1 = new Thread(new Runnable(){ @Override public void run() { myQueue.put("FFF"); myQueue.put("GGG"); } },"t1"); t1.start(); Thread t2 = new Thread(new Runnable(){ @Override public void run() { Object o1 = myQueue.take(); System.out.println("移除的元素为:" + o1); Object o2 = myQueue.take(); System.out.println("移除的元素为:" + o2); } },"t2"); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } }
【运行结果】