(See http://www.suneca.com/article.asp?id=56)
七,对象的wait()、notify()和notifyAll()用法
1)Object 类定义了 wait()、notify() 和 notifyAll() 方法。可以让线程相互通知事件的发生。要执行这些方法,必须拥有相关对象的锁。
2)wait() 会让调用线程休眠,直到用 Thread.interrupt() 中断它、过了指定的时间、或者另一个线程用 notify() 或 notifyAll() 唤醒它。
3)当对某个对象调用 notify() 时,如果有任何线程正在通过 wait() 等待该对象,那么就会唤醒其中一个线程。当对某个对象调用 notifyAll() 时,会唤醒所有正在等待该对象的线程。
假如我们有两条线程,我们希望线程的输出顺序是:
线程t1输出十次
线程t2输出十次
线程t1输出十次
线程t2输出十次
那程序该如何实现?
我们的设计思路是:
使用锁的机制,首先,线程1进入可运行状态后
1)线程t1获取对象的锁
2)线程t1完成输出十个数的任务
3)唤醒其他(t2)正在等待的线程
4)自身阻塞,释放锁。
5)线程t2获取锁
6)线程t2完成输出十个数的任务
7)唤醒其他(t1)正在等待的线程
8)自身阻塞,释放锁。
9)。。。。
程序的实现如下:
1)Object 类定义了 wait()、notify() 和 notifyAll() 方法。可以让线程相互通知事件的发生。要执行这些方法,必须拥有相关对象的锁。
2)wait() 会让调用线程休眠,直到用 Thread.interrupt() 中断它、过了指定的时间、或者另一个线程用 notify() 或 notifyAll() 唤醒它。
3)当对某个对象调用 notify() 时,如果有任何线程正在通过 wait() 等待该对象,那么就会唤醒其中一个线程。当对某个对象调用 notifyAll() 时,会唤醒所有正在等待该对象的线程。
假如我们有两条线程,我们希望线程的输出顺序是:
线程t1输出十次
线程t2输出十次
线程t1输出十次
线程t2输出十次
那程序该如何实现?
我们的设计思路是:
使用锁的机制,首先,线程1进入可运行状态后
1)线程t1获取对象的锁
2)线程t1完成输出十个数的任务
3)唤醒其他(t2)正在等待的线程
4)自身阻塞,释放锁。
5)线程t2获取锁
6)线程t2完成输出十个数的任务
7)唤醒其他(t1)正在等待的线程
8)自身阻塞,释放锁。
9)。。。。
程序的实现如下:
程序代码
package
zizz
;
/**
* 主程序. 使用wait(),notify(),notifyAll()方法
*
* @author <a href='http://www.suneca.com'>ZIZZ</a>
*
* @Create-Time:2008-4-21 上午12:51:59
*/
public class ThreadLock {
public static void main (String [ ] args ) {
//共享线程实例的线程.
ShareRunnable share = new ShareRunnable ( ) ;
Thread t1 = new Thread (share , "t1" ) ;
Thread t2 = new Thread (share , "t2" ) ;
t1 .start ( ) ;
t2 .start ( ) ;
}
}
/**
*
* @author <a href='http://www.suneca.com'>ZIZZ</a>
*
* @Create-Time:2008 上午12:14:26
*/
class ShareRunnable implements Runnable {
public void run ( ) {
//第一个线程运行时,对共享的线程对象进行加锁
synchronized ( this ) {
for ( int i = 1 ; i < = 100 ; i + + ) {
//输出当前的值
System .out .println (Thread .currentThread ( ) .getName ( ) + " : " + i ) ;
// 如果i为10的倍数
if (i % 10 = = 0 ) {
try {
// 唤起其他线程
notifyAll ( ) ;
// 当前正在运行的线程阻塞,释放拥有该对象的锁.
if (i = = 100 ) break ;
else wait ( ) ;
} catch (InterruptedException e ) {
e .printStackTrace ( ) ;
}
}
}
}
}
}
/**
* 主程序. 使用wait(),notify(),notifyAll()方法
*
* @author <a href='http://www.suneca.com'>ZIZZ</a>
*
* @Create-Time:2008-4-21 上午12:51:59
*/
public class ThreadLock {
public static void main (String [ ] args ) {
//共享线程实例的线程.
ShareRunnable share = new ShareRunnable ( ) ;
Thread t1 = new Thread (share , "t1" ) ;
Thread t2 = new Thread (share , "t2" ) ;
t1 .start ( ) ;
t2 .start ( ) ;
}
}
/**
*
* @author <a href='http://www.suneca.com'>ZIZZ</a>
*
* @Create-Time:2008 上午12:14:26
*/
class ShareRunnable implements Runnable {
public void run ( ) {
//第一个线程运行时,对共享的线程对象进行加锁
synchronized ( this ) {
for ( int i = 1 ; i < = 100 ; i + + ) {
//输出当前的值
System .out .println (Thread .currentThread ( ) .getName ( ) + " : " + i ) ;
// 如果i为10的倍数
if (i % 10 = = 0 ) {
try {
// 唤起其他线程
notifyAll ( ) ;
// 当前正在运行的线程阻塞,释放拥有该对象的锁.
if (i = = 100 ) break ;
else wait ( ) ;
} catch (InterruptedException e ) {
e .printStackTrace ( ) ;
}
}
}
}
}
}
运行结果片断:

假如在开发的时候,并没有写上 synchronized (this) {...}的同步语句,那将会出现一些问题,因为使用wait()、notify(),它需要有 owner,假如没有写上这个同步语句块,那系统将会执出如下错误信息:
程序代码
Exception in thread "t1" java.lang.IllegalMonitorStateException:
current thread not owner
at java.lang.Object.notifyAll(Native Method)
at zizz.ShareRunnable.run(ThreadLock.java:41)
at java.lang.Thread.run(Thread.java:595)
at java.lang.Object.notifyAll(Native Method)
at zizz.ShareRunnable.run(ThreadLock.java:41)
at java.lang.Thread.run(Thread.java:595)