在Java多线程编程中,sleep()与wait()的区别是面试中的经典问题。下面,我们尝试用一个生动的比喻来彻底理解这两个方法的本质。
想象你是一位镇守边关的将军——就叫你“线程将军”。你的城池就是一段代码,你手里的兵符就是“锁”,有了它,你就能指挥城里所有资源。
现在朝廷传来命令,让你暂停进攻,原地待命一天。
-
第一种选择,你采用“sleep闭关法”。 你关闭城门,抱着兵符在床上睡一整天。这期间,不管外面是敌军来袭,还是友军送粮,你一概不理。一天后,你自然醒来,继续工作。
但这带来了一个问题:因为兵符在你手里睡觉,友军进不了城,传不了信,只能在城外干等。这就是sleep()的问题——你持锁休眠,别的线程只能傻等。
-
第二种选择,你采用“wait待援法”。 你先把兵符放在城楼案上,然后退入后堂休息。但同时你交代士兵:“如有援军消息,立刻叫醒我。”
这时兵符空出来了,其他将军就能进城取走兵符,调用城里的粮草兵马。等他们办完事,或者有你需要的情报,就会通过notify()唤醒你,并把兵符还给你。
核心区别由此显现:
sleep()是 “抱着锁睡觉,到点自然醒” 。
wait()是 “放下锁等待,等人叫才醒” 。
其他关键差异点:
- 灵活性:
sleep()的将军很固执,说睡多久就必须到点才醒。wait()的将军则灵活,可以设置超时时间,也可以被随时唤醒。
- 依赖性:
sleep()可独立使用。wait()必须配合notify()或notifyAll()使用,否则将军可能永远等下去。
- 使用场景:
sleep()像在自家卧室睡觉,随时可以。wait()则必须在特定的安全环境下使用,即必须在synchronized同步代码块或方法中调用,这确保了“放下兵符”和“开始等待”是一个不可分割的原子操作,防止状态不一致。更多关于并发控制的知识,可以参考网络/系统相关专题。
- 归属不同:
sleep()是Thread类的静态方法。wait()是Object类的方法,任何对象都可以作为锁和等待的监视器。
总结比喻
在多线程的协作中,sleep()如同闭关守关的将军,持锁而眠,定时自醒,简单直接但可能阻塞整体流程。wait()则像待援的智者,释锁而待,听召方起,灵活高效但需与notify()机制协同工作。理解这一者的区别,是掌握线程间通信与同步的关键一步。
|