内存队列Demo
public class MyQueue {private final static int MAX_SIZE = 100;private LinkedList<String> queue = new LinkedList<String>();/*** 添加元素*/public synchronized void offer(String element) {try {if (queue.size() == MAX_SIZE) {//一个线程只要执行到这一步了,就意味着这个线程获取到锁了//当这个队列满了就可以让线程进入一个等待的状态,释放掉锁wait();}queue.addLast(element);//放入元素后,唤醒别的线程notifyAll();} catch (InterruptedException e) {e.printStackTrace();}}/*** 获取元素*/public synchronized String take() {String element = null;try {if (queue.size() == 0) {wait(); //将锁释放掉,等待别的线程去执行放入数据的操作}element = queue.removeFirst();notifyAll();//唤醒当前等待这个锁的线程} catch (Exception e) {e.printStackTrace();}return element;}}
wait和notify / notifyAll还是挺有用的,在多线程开发中,还是挺常见的,一般用来做线程通信,某个线程可以处于等待状态,其他线程可以来通知他唤醒他。
实际上wait和notify / notifyAll其实主要是用来控制线程的,和volatile、synchronzied也都是控制线程的
wait和notify底层原理
当线程调用了wait()时,当前线程被加入到实例对象中的C++锁对象wait set队列里,同时monitor计数器减一。
当别的线程调用了notifyAll()时,把waitset队列里的线程唤醒。
加锁的时候必须对同一个对象实例进行加锁,因为这两个方法操作的都是一个对象实例中的那个monitorObject,只有这样wait和notify操作的才是同一套东西
wait和notify注意事项
- wait
- wait与sleep的区别:前者释放锁,后者不释放锁
- wait(),必须是有人notify唤醒他,wait(timeout),阻塞一段时间,然后自己唤醒,继续争抢锁
- notify
- notify()与notifyall():前者就唤醒block状态的一个线程,后者唤醒block状态的所有线程
- wait与notify,必须在synchronized代码块中使用,因为必须是拥有monitor lock的线程才可以执行wait与notify操作。因此wait与notify,必须与synchornized一起,对同一个对象进行使用,这样他们对应的monitor才是一样的
