大家都知道java中的object对象除了hashcode equals这些方法外,还有非常重要的两个方法就是wait和notify
wait 等待
notify 唤醒
先看现象 再做推导和结论 如下所示
上图直接运行会报异常 如下所示
上面异常百度会搜索很多答案出来 我来简单概括一下
一个对象要想用wait方法 则调用wait方法的这个对象所处的线程必须持有这个对象的锁, 即synchronized(object)
如下图所示
但是这样主线程一直在等待之中 "已经醒来"是不会被打印的 那么如何让已经醒来也打印呢 这个时候notify方法就派上用场了
A线程wait B线程notify通知A线程醒来 如下图所示
new Thread(new Runnable() { @Override public void run() { System.out.println("线程A等待获取lock锁"); synchronized (lock) { try { System.out.println("线程A获取了lock锁"); Thread.sleep(1000); System.out.println("线程A将要运行lock.wait()方法进行等待"); lock.wait(); System.out.println("线程A等待结束"); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { System.out.println("线程B等待获取lock锁"); synchronized (lock) { System.out.println("线程B获取了lock锁"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程B将要运行lock.notify()方法进行通知"); lock.notify(); } } }).start();
线程A等待获取lock锁
线程A获取了lock锁
线程B等待获取lock锁
线程A将要运行lock.wait()方法进行等待
线程B获取了lock锁
线程B将要运行lock.notify()方法进行通知
线程A等待结束
从上面打印结果来看 的确线程B执行了lock.notify方法以后 处于wait状态的线程A又执行了wait方法之后的代码
从上面的结果也说明了一个结果 处于wait状态以后线程A自动释放了锁,不然线程B是不会执行synchronized的方法的。
那么重头戏来了,接下来的这个思考方式我相信整个搜索引擎都没有提到过,上面只有一个线程等待一个线程唤醒的情况
那么如果此时再来一个线程等待的话 线程B会唤醒哪一个线程呢
如下所示 加入线程C等待
new Thread(new Runnable() { @Override public void run() { System.out.println("线程C等待获取lock锁"); synchronized (lock) { System.out.println("线程C获取了lock锁"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程C将要运行lock.wait()方法进行等待"); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程C等待结束"); } } }).start();
你们可以试一下 无论执行多少次 都是谁最先等待 最先唤醒谁 而且另外一个会一直处于等待中
那么有什么方法可以全部唤醒等待线程呢 很简单notifyall方法可以 但是前提是这个唤醒线程 必须最后执行 可以里面加个线程休眠时间设置长一点
我的博客就是这样 不讲概念 只讲现象 让你自己去感悟 涨知识的话加个关注