wait()和notify()是直接隸屬於Object類,也就是說,全部對象都擁有這一對方法。初看起來這十分 難以想象,可是實際上倒是很天然的,由於這一對方法阻塞時要釋放佔用的鎖,而鎖是任何對象都具備的,調用任意對象的 wait() 方法致使線程阻塞,而且該對象上的鎖被釋放。而調用任意對象的notify()方法則致使因調用該對象的wait() 方法而阻塞的線程中隨機選擇的一個解除阻塞(但要等到得到鎖後才真正可執行)。算法
其次,wait()和notify()可在任何位置調用,可是這一對方法卻必須在 synchronized 方法或塊中調用,理由也很簡單,只有在 synchronized 方法或塊中當前線程才佔有鎖,纔有鎖能夠釋放。一樣的道理,調用這一對方法的對象上的鎖必須爲當前線程所擁有,這樣纔有鎖能夠 釋放。所以,方法調用必須放置在這樣的 synchronized 方法或塊中,該方法或塊的加鎖對象就是調用這些方法的對象。若不知足這一條 件,則程序雖然仍能編譯,但在運行時會出現IllegalMonitorStateException 異常。
wait() 和 notify() 方法的上述特性決定了它們常常和synchronized 方法或塊一塊兒使用,將它們和操做系統的進程間通訊機制做 一個比較就會發現它們的類似性:synchronized方法或塊提供了相似於操做系統原語的功能,它們的執行不會受到多線程機制的干擾,而這一對方法則 至關於 block 和wakeup 原語(這一對方法均聲明爲 synchronized)。它們的結合使得咱們能夠實現操做系統上一系列精妙的進程間 通訊的算法(如信號量算法),並用於解決各類複雜的線程間通訊問題。
關於 wait() 和 notify() 方法最後再說明兩點:
第一:調用 notify() 方法致使解除阻塞的線程是從因調用該對象的 wait() 方法而阻塞的線程中隨機選取的,咱們沒法預料哪個線程將會被選擇,因此編程時要特別當心,避免因這種不肯定性而產生問題。
第二:除了 notify(),還有一個方法 notifyAll() 也可起到相似做用,惟一的區別在於,調用 notifyAll() 方法將把因調 用該對象的 wait() 方法而阻塞的全部線程一次性所有解除阻塞。固然,只有得到鎖的那一個線程才能進入可執行狀態。
相關wait和notify使用demo:
01
/**
02
* <pre>
03
* 子線程循環10次,接着主線程循環100次,接着有回到子線程循環10次,
04
* 接着再回到主線程循環100次,如此執行50次
05
* </pre>
06
* @author ketqi
07
*/
08
public
class WaitNotifyDemo {
09
public
static
void main(String[] args) {
10
11
final Business business =
new Business();
12
new Thread(
new Runnable() {
13 @Override
14
public
void run() {
15
for (
int i =
1; i <=
50; i++) {
16 business.
sub(i);
17 }
18
19 }
20 }).
start();
21
22
for (
int i =
1; i <=
50; i++) {
23 business.
main(i);
24 }
25 }
26 }
27
28
class Business {
29
private
boolean isMainThread =
true;
30
31
public
synchronized
void sub(
int i) {
32
while (!isMainThread) {
33
try {
34
this.
wait();
35 }
catch (InterruptedException e) {
36 e.
printStackTrace();
37 }
38 }
39
for (
int j =
1; j <=
10; j++) {
40 System.
out.
println(
"sub thread sequence of " + j +
",loop of " + i);
41 }
42 isMainThread =
false;
43
this.
notify();
44 }
45
46
public
synchronized
void main(
int i) {
47
while (isMainThread) {
48
try {
49
this.
wait();
50 }
catch (InterruptedException e) {
51 e.
printStackTrace();
52 }
53 }
54
for (
int j =
1; j <=
100; j++) {
55 System.
out.
println(
"main thread sequence of " + j +
",loop of " + i);
56 }
57 isMainThread =
true;
58
this.
notify();
59 }
60 }