JDK源码笔记--Object
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public final native Class<?> getClass(); public native int hashCode(); public boolean equals(Object obj) { return ( this == obj); } protected native Object clone() throws CloneNotSupportedException; public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } public final native void notify(); public final native void notifyAll(); public final native void wait( long timeout) throws InterruptedException; public final void wait() throws InterruptedException { wait( 0 ); } protected void finalize() throws Throwable { } |
重点看看wait(),notify(),notifyAll()方法
首先是都是final native 修饰的。
monitor
暂且译成监听器,相当于对象锁。
notify的注释:
1 2 3 4 5 6 | /** * Wakes up a single thread that is waiting on this object's * monitor. If any threads are waiting on this object, one of them * is chosen to be awakened. The choice is arbitrary and occurs at * the discretion of the implementation. A thread waits on an object's * monitor by calling one of the { @code wait} methods. |
唤醒正在等待该对象的单个线程,如果有多个线程在等待获取某个对象的监听器,只唤醒其中一个。
1 2 | @throws IllegalMonitorStateException if the current thread is not * the owner of this object's monitor. |
如果当前线程没拥有监听器就抛异常 IllegalMonitorStateException,这就是为什么notify,notifyAll必须在synchronized代码中执行。
notifyAll的注释:
1 2 3 4 | /** * Wakes up all threads that are waiting on this object's monitor. A * thread waits on an object's monitor by calling one of the * { @code wait} methods. |
唤醒在该对象监视器上等待的所有线程,但是只有一个最终获得监听器。
1 2 | @throws IllegalMonitorStateException if the current thread is not * the owner of this object's monitor. |
同上。
wait的注释:
1 2 3 4 5 | /** * Causes the current thread to wait until either another thread invokes the * { @link java.lang.Object#notify()} method or the * { @link java.lang.Object#notifyAll()} method for this object, or a * specified amount of time has elapsed. |
1 2 3 4 5 6 7 8 9 10 11 12 | * <ul> * <li>Some other thread invokes the { @code notify} method for this * object and thread <var>T</var> happens to be arbitrarily chosen as * the thread to be awakened. * <li>Some other thread invokes the { @code notifyAll} method for this * object. * <li>Some other thread { @linkplain Thread#interrupt() interrupts} * thread <var>T</var>. * <li>The specified amount of real time has elapsed, more or less. If * { @code timeout} is zero, however, then real time is not taken into * consideration and the thread simply waits until notified. * </ul> |
导致当前线程等待,直到另一个线程调用notify(),notifyAll(),线程中断,或者超过指定的时间。
当调用wait(),实际上是调用的wait(0)表示无限等下去,也可以指定如wait(1000)表示等待一秒就继续执行。
wait()方法会放弃对象锁,sleep()不会。
1 2 3 4 5 6 7 8 9 10 | * the condition that should have caused the thread to be awakened, and * continuing to wait if the condition is not satisfied. In other words, * waits should always occur in loops, like this one: * <pre> * synchronized (obj) { * while (<condition does not hold>) * obj.wait(timeout); * ... // Perform action appropriate to condition * } * </pre> |
建议wait(time)的方法放在while循环中。
1 2 3 4 5 | * @throws IllegalArgumentException if the value of timeout is * negative. * @throws IllegalMonitorStateException if the current thread is not * the owner of the object's monitor. * @throws InterruptedException if any thread interrupted the |
当时间参数not in the range 0-999999,抛异常IllegalArgumentException
当线程未获得对象锁,抛异常IllegalMonitorStateException。这就是wait()要在synchronized中执行。
当线程被中断,抛异常InterruptedException
一个栗子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public class Test2 implements Runnable { static Object a = new Object(); public static void main(String[] args) throws InterruptedException { Test2 t2 = new Test2(); Thread thread = new Thread(t2); thread.start(); //TimeUnit.MILLISECONDS.sleep(1000); synchronized (a) { System.out.println( "notify start" +System.currentTimeMillis()); a.notify(); System.out.println( "notify end" +System.currentTimeMillis()); } } @Override public void run() { synchronized (a) { try { System.out.println( "wait start" + System.currentTimeMillis()); a.wait(); System.out.println( "wait end" + System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } } } |
当TimeUnit.MILLISECONDS.sleep(1000);注释掉时,控制台:
1 2 3 | notify start1517303479751 notify end1517303479752 wait start1517303479752 |
notify执行完了才执行wait,导致wait不能结束。意味着执行顺序不能依赖代码先后顺序。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
· 你所不知道的 C/C++ 宏知识
· 不到万不得已,千万不要去外包
· C# WebAPI 插件热插拔(持续更新中)
· 会议真的有必要吗?我们产品开发9年了,但从来没开过会
· 【译】我们最喜欢的2024年的 Visual Studio 新功能
· 如何打造一个高并发系统?