使用wait/notify模拟queue
BlockingQueue:顾名思义,首先它是一个队列,并且支持阻塞的机制,阻塞的放入和得到数据。我们要实现LinkedBlockingQueue,下面两个简单的方法put和take。
put(anObject):把anObject加到BlockingQueue,如果BlockingQueue中没有空间,则调用此方法的线程被阻断,直到BlockingQueue里有空间再继续。
take:取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的数据被加入
1 package com.java.day02_notify_wait; 2 3 import java.util.LinkedList; 4 import java.util.concurrent.atomic.AtomicInteger; 5 6 /** 7 * 用wait和notify模仿queue 8 * 9 * @author syousetu 10 * 11 */ 12 public class MyQueue { 13 // 先创建一个容器,有上限和下限 14 15 // 1.创建一个列表 16 private volatile LinkedList<Object> list = new LinkedList<Object>(); 17 18 // 2.设置列表的上限 19 private final int max; 20 21 // 3.设置列表的下限 22 private int min = 0; 23 24 // 构造器 25 public MyQueue(int len) { 26 this.max = len; 27 } 28 29 // 计数器 30 private AtomicInteger count = new AtomicInteger(0); 31 32 // 要使用到synchronized 所以要创建一个锁 33 private final Object lock = new Object(); 34 35 // put(Object) 36 37 public void put(Object obj) { 38 synchronized (lock) { 39 // 队列队伍已满,请等待 40 while (count.get() == max) { 41 try { 42 lock.wait(); 43 } catch (InterruptedException e) { 44 e.printStackTrace(); 45 } 46 } 47 48 // 给列表添加元素 49 list.add(obj); 50 // 计数器增加一 51 count.incrementAndGet(); 52 // 通知另外一个线程可以进行取元素 53 lock.notify(); 54 System.out.println("已成功添加元素:" + obj); 55 56 } 57 58 } 59 60 // take() 61 62 public Object take() { 63 Object obj = null; 64 65 synchronized (lock) { 66 // 队列里没有元素,请等待,释放锁 67 while (count.get() == min) { 68 try { 69 lock.wait(); 70 } catch (InterruptedException e) { 71 e.printStackTrace(); 72 } 73 } 74 75 // 移除第一个元素 76 obj = list.removeFirst(); 77 // 通知另一个线程可以进行存放 78 lock.notify(); 79 // 计数器减一 80 count.decrementAndGet(); 81 System.out.println("已成功取出元素"); 82 83 } 84 85 return obj; 86 } 87 88 public int getSize() { 89 return list.size(); 90 } 91 92 public static void main(String[] args) { 93 final MyQueue mq = new MyQueue(5); 94 95 mq.put("a"); 96 mq.put("b"); 97 mq.put("c"); 98 mq.put("d"); 99 mq.put("e"); 100 101 System.out.println("当前队列的大小:"+mq.getSize()); 102 103 Thread t1 = new Thread(new Runnable() { 104 public void run() { 105 mq.put("f"); 106 mq.put("g"); 107 } 108 },"t1"); 109 110 111 Thread t2 = new Thread(new Runnable() { 112 public void run() { 113 for (int i = 0; i < 3; i++) { 114 System.out.println(Thread.currentThread().getName()+"线程取出元素:"+mq.take()); 115 } 116 117 } 118 }); 119 120 t1.start(); 121 t2.start(); 122 123 } 124 125 }
运行结果:
1 已成功添加元素:a 2 已成功添加元素:b 3 已成功添加元素:c 4 已成功添加元素:d 5 已成功添加元素:e 6 当前队列的大小:5 7 已成功取出元素 8 Thread-0线程取出元素:a 9 已成功添加元素:f 10 已成功取出元素 11 Thread-0线程取出元素:b 12 已成功添加元素:g 13 已成功取出元素 14 Thread-0线程取出元素:c