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 }