|
| 1 | +## wait()和sleep()的区别 |
| 2 | + |
| 3 | +### 问题: |
| 4 | +在线程里`wait()`和`sleep()`的区别? |
| 5 | +我的理解是一条`wait()`线程语句后,仍然在运行这个模块,并且占用CPU,但是一条`sleep()`语句并不会占用CPU,对吗? |
| 6 | +为什么需要`sleep()`和`wait()`两条语句:他们在底层是怎么执行的? |
| 7 | + |
| 8 | +### 回答: |
| 9 | +[`wait`](http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#wait%28%29)可以被另一个进程唤醒通过调用[`notify`](http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#notify%28%29)而`sleep`不行。并且`wait`和`notify`必须在监控对象同步块内发生而`sleep`不行。 |
| 10 | +``` |
| 11 | +Object mon = ...; |
| 12 | +synchronized (mon) { |
| 13 | + mon.wait(); |
| 14 | +} |
| 15 | +``` |
| 16 | +在此刻正在执行的线程`wait`后释放了监视器。另外一个线程可能在做 |
| 17 | +``` |
| 18 | +synchronized (mon) { mon.notify(); } |
| 19 | +``` |
| 20 | +(同一个`mon`对象)第一个线程(假设它是唯一在监视器上等待的线程)将会唤醒。 |
| 21 | +如果有很多的线程在等待你可以调用[`notifyall`](http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#notifyAll%28%29)来唤醒。但是只有其中之一能抢夺到该对象的监视器并继续执行(`wait`是在`synchronized `块内)。其他的线程会被锁住直到他们获得监视器的锁。 |
| 22 | +另外就是你可以`wait`对象本身(例如:你可以`wait`一个对象的监视器)但是你只能`sleep`线程。 |
| 23 | +另外还有你可能会得到伪唤醒(例如:等待的线程没有任何操作就唤醒了) |
| 24 | +如果你按照下面的做法,你就能一直处于等待的状态尽管出现一些原因使他唤醒了。 |
| 25 | +``` |
| 26 | +synchronized { |
| 27 | + while (!condition) { mon.wait(); } |
| 28 | +} |
| 29 | +``` |
| 30 | +(wait前会释放监视器,被唤醒后又要重新获取,这瞬间可能有其他线程刚好先获取到了监视器,从而导致状态发生了变化, 这时候用while循环来再判断一下条件(比如队列是否为空)来避免不必要或有问题的操作。) |
| 31 | + |
| 32 | +**stackoverflow链接:** |
| 33 | +http://stackoverflow.com/questions/1036754/difference-between-wait-and-sleep |
| 34 | + |
| 35 | +### 相关问题及链接: |
| 36 | + |
| 37 | +1. [Java: notify() vs. notifyAll() all over again](http://stackoverflow.com/questions/37026/java-notify-vs-notifyall-all-over-again) |
| 38 | +2. [线程通信](http://ifeve.com/thread-signaling/) |
0 commit comments