java线程的notify_java线程notify(), wait()的使用

回顾一个比较经典的线程间协作的问题:启动三个线程,每个线程相应的打印10遍A,10遍B,10遍C。要求三个线程交替执行,输处10遍ABC。

用Object类的notify(), wait()方法可实现上述要求。

Object.notify()可以唤醒一个线程,使之进入就绪状态,等待获取对象锁后运行。

Object.wait()方法可以使一个线程进入阻塞状态,然后释放对象锁,等待被notify()方法唤醒。

因为notify()和wait()方法都跟对象锁相关,所以必须在同步块里面被调用才有效。即都是如下形式:

synchronized(Obj){

try{

Obj.wait();

} catch (Exception e){

...

}

Obj.notify;

}

回看题目本身。要交替打印A,B,C,建立需要三个线程,三个对象。单个打印时,线程需要得到两个对象锁。

public class WatiNotifyTest {

public static void main(String[] args) {

Object obj1 = new Object();

Object obj2 = new Object();

Object obj3 = new Object();

MyThread myThread1 = new MyThread("A", obj1, obj2);

MyThread myThread2 = new MyThread("B", obj3, obj1);

MyThread myThread3 = new MyThread("C", obj2, obj3);

myThread1.start();

myThread2.start();

myThread3.start();

}

}

class MyThread extends Thread {

private String name;

private Object a;

private Object b;

public MyThread(String name, Object a, Object b){

this.name = name;

this.a = a;

this.b = b;

}

@Override

public void run() {

int count = 10;

while(count > 0){

synchronized(a){

synchronized (b) {

System.out.println(name);//print "A" or "B" or "C".

count--;

/****************/

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

/****************/

b.notify();//wake up the thread which is waiting for the lock of "b".

}

try {

a.wait();//let current thread release the lock on a.

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

线程对象MyThread的run方法会执行10次循环,每次循环都打印出当前线程的name(A或B或C)。而两个synchronized块是实现交替打印的关键。

从main方法入手。建立三个对象,obj1,ojb2,obj3,共有三把对象锁。线程myThread1启动,执行myThread1的run方法。同理,myThread2,myThread3启动,执行各自的run方法。对于myThread1来说,a就是obj1,b就是obj2。同理,对于myThread2来说,a就是obj3,b就是obj1。如下是程序运行步骤:

1、myThread1进入while循环,进入synchronized块。myThread1获得了obj1和obj2两个对象锁。然后输出"A",sleep 10毫秒。调用obj2.notify(),唤醒在等待obj2的线程;调用obj1.wait(),释放obj1的锁。

2、在上述myThread1执行的过程中,myThread2进入while循环,然而它暂时只能进入第一个synchronized块,因为它需要obj1的锁才能进入第二个synchronized块,而此时obj1的锁在myThread1手中。当myThread1调用obj1.wait()之后,myThread2进入第二个synchronized块,获得obj3和obj1两个对象锁,然后输出"B",sleep 10毫秒,调用obj1.notify(),唤醒在等待obj1的线程;调用obj3.wait(),释放obj3的锁.

3、在myThread1执行完obj2.notify()并退出第二个synchronized块的时候,myThread3得到了obj2的对象锁,进入第一个synchronized块。当myThread2执行完obj3.wait()之后,获得obj3的对象锁,进入第二个synchronized块。然后输出"C",sleep 10毫秒。调用obj3.notify(),唤醒在等待obj3的线程;调用obj2.wait(),释放obj2的锁。

4、myThread1在第一次循环执行完后进入waiting状态,等待的是obj1的锁,以便进入第一个synchronized块。而当myThread2执行完毕的时候,调用了obj1.notify(),此时myThread1再次进入第一个synchronized块。等待myThread3执行完obj2.wait()释放obj2的锁之后,myThread1进入第二个synchronized块。然后重复1,2,3,4的步骤。

代码中/*****/之间的部分很重要,它保证了三个线程的执行顺序不受JVM随机调度的影响。

从上面例子可以看出,wait()和notify()方法,主要是控制对象的使用权的。notify()相当于告诉在waiting状态的线程说,某某资源我已经用完了,你可以来使用了。wait()方法相当于自动让出资源的使用权,进入阻塞状态(类似sleep,但是sleep会保留对象锁)。

注意wait()和notify()一般是一起使用的。在调用了Object.wait()的线程,只有在Object.notify()被调用之后,才能再次进入就绪状态,等待调度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值