Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4491d47

Browse filesBrowse files
committed
优化“wait()和sleep()的区别”一文
1 parent 49541e8 commit 4491d47
Copy full SHA for 4491d47

File tree

Expand file treeCollapse file tree

1 file changed

+32
-11
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+32
-11
lines changed
+32-11Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,53 @@
11
## wait()和sleep()的区别
22

33
### 问题:
4-
在线程里`wait()``sleep()`的区别?
5-
我的理解是一条`wait()`线程语句后,仍然在运行这个模块,并且占用CPU,但是一条`sleep()`语句并不会占用CPU,对吗?
6-
为什么需要`sleep()``wait()`两条语句:他们在底层是怎么执行的?
4+
在线程里 `wait()``sleep()` 的区别?
5+
6+
我的理解是执行 `wait()` 语句后,该线程仍是运行态,并且会占用CPU,但是执行 `sleep()`后,该线程则不会占用CPU,对吗?
7+
8+
为什么需要 `sleep()``wait()` 两条语句:他们底层是如何实现的?
79

810
### 回答:
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`不行。
11+
线程 在[`wait`](http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#wait%28%29) 后,可以被另一个拥有相同 `synchronized ` 对象的线程,通过调用[ `notify` ](http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#notify%28%29)唤醒,而 `sleep` 不行。`wait``notify` 能正常执行的条件是(否则会抛异常):多个线程的代码,都包在`synchronized `块中,并且 `synchronized` 锁的对象需要是同一个。如下所示:
1012
```
1113
Object mon = ...;
1214
synchronized (mon) {
1315
mon.wait();
1416
}
1517
```
16-
在此刻正在执行的线程`wait`后释放了监视器。另外一个线程可能在做
18+
上面这个线程调用了 `wait`后,会进入等待状态。这时另外一个线程可以这样做:
1719
```
1820
synchronized (mon) { mon.notify(); }
1921
```
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-
如果你按照下面的做法,你就能一直处于等待的状态尽管出现一些原因使他唤醒了。
22+
可以看到,`synchronized`锁对象,都是mon。因此,当第二个线程调用了 `notify()` 方法,第一个线程就会唤醒(假设有且仅有一个线程是被包在 `synchronized (mon)` 中且处于等待状态)。
23+
24+
如果有多个线程在等待(且`synchronized` 锁对象是同一个,如上例中的mon),则可以调用[ `notifyAll` ](http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#notifyAll%28%29)来唤醒。但是,只有其中一个线程能抢到锁并继续执行(因为 `wait` 的线程都是在 `synchronized` 块内,需要争夺 `synchronized` 锁)。其他的线程会被锁住,直到他们依次获得锁。
25+
26+
再补充几点:
27+
1. `wait` 方法由 `Object` 对象调用(例如:你可以让 `synchronized` 锁对象调用 `wait` ,如上面例子的mon.wait()),而 `sleep` 则由线程调用。
28+
29+
2. `wait` 之后,可能会伪唤醒(`spurious wakeups`)(正在waiting的线程,无故就被唤醒了,如遇到interrupted, timing out等情况)。因此,你需要多设置一些检查,如果不满足实际的运行条件,则继续等待,如下:
2530
```
2631
synchronized {
2732
while (!condition) { mon.wait(); }
2833
}
2934
```
30-
(wait前会释放监视器,被唤醒后又要重新获取,这瞬间可能有其他线程刚好先获取到了监视器,从而导致状态发生了变化, 这时候用while循环来再判断一下条件(比如队列是否为空)来避免不必要或有问题的操作。)
35+
36+
3. 当线程调用 `sleep` 时,并没有释放对象锁,而 `wait` 则释放了对象锁:
37+
```
38+
synchronized(LOCK) {
39+
Thread.sleep(1000); // LOCK is held
40+
}
41+
synchronized(LOCK) {
42+
LOCK.wait(); // LOCK is not held
43+
}
44+
```
45+
46+
最后,再小结一下:
47+
- ` sleep() `:“我已经完成了一个时间片,**在n微秒**前,请不要再给我一个时间片”。这时操作系统不会让这个线程做任何事情,直到sleep时间结束。
48+
- ` wait() `:"我已经完成了一个时间片,**在其他线程调用` notify() `**,请不要再给我一个时间片)。这时操作系统不会安排这个线程继续运行,直到有人调用了` notify() `
49+
50+
3151

3252
**stackoverflow链接:**
3353
http://stackoverflow.com/questions/1036754/difference-between-wait-and-sleep
@@ -36,3 +56,4 @@ http://stackoverflow.com/questions/1036754/difference-between-wait-and-sleep
3656

3757
1. [Java: notify() vs. notifyAll() all over again](http://stackoverflow.com/questions/37026/java-notify-vs-notifyall-all-over-again)
3858
2. [线程通信](http://ifeve.com/thread-signaling/)
59+
3. [最简实例说明wait、notify、notifyAll的使用方法](http://longdick.iteye.com/blog/453615)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.