Java-线程Thread等待与唤醒

本文介绍了Java中线程间的等待与唤醒机制,包括notify(), notifyAll(), wait()等方法的使用示例及原理解析。
Java线程的等待与唤醒主要包括几个方法:
(1)notify():唤醒在此对象监视器上等待的单个线程。
(2)notifyAll():唤醒在此对象监视器上等待的所有线程。
(3)wait():让当前线程处于阻塞状态,同时释放它所持有的锁。
(4)wait(long timeout):让线程处于阻塞状态,直到其他线程调用此对象的notify()或者notifyAll()方法,或者超过指定的时间量,当前线程被唤醒。

(5)wait(long timeout,int nanos):同上。

wait()和notify()函数示例:

[java]  view plain  copy
  1. class ThreadA extends Thread{  
  2.   
  3.     public ThreadA(String name) {  
  4.         super(name);  
  5.     }  
  6.     public void run() {  
  7.         synchronized (this) {  
  8.             System.out.println(Thread.currentThread().getName()+" call notify()");  
  9.             // 唤醒当前的wait线程  
  10.             notify();  
  11.         }  
  12.     }  
  13. }  
  14. public class WaitTest {  
  15.   
  16.     public static void main(String[] args) {  
  17.         ThreadA t1 = new ThreadA("t1");  
  18.         synchronized(t1) {  
  19.          try {  
  20.                 // 启动“线程t1”  
  21.                 System.out.println(Thread.currentThread().getName()+" start t1");  
  22.                 t1.start();  
  23.                 // 主线程等待t1通过notify()唤醒。  
  24.                 System.out.println(Thread.currentThread().getName()+" wait()");  
  25.                 t1.wait();  
  26.                 System.out.println(Thread.currentThread().getName()+" continue");  
  27.               } catch (InterruptedException e) {  
  28.                 e.printStackTrace();  
  29.             }  
  30.         }  
  31.     }  
  32. }  

运行结果:
main start t1
main wait()
t1 call notify()
main continue

对于结果可能有些人不理解第二个输出(main wait),说明此时main线程还在运行着, 其实t1.wait()的意思含义是停止当前的线程,当然就是CPU上正在运行的程序,这样整个的结果输出就比较合理,t1在运行run()函数会运行notify(),main线程开始重新运行。

wait(long timeout)和notify()函数:
示例程序:
[java]  view plain  copy
  1. // WaitTest.java的源码  
  2. class ThreadA extends Thread{  
  3.   
  4.     public ThreadA(String name) {  
  5.         super(name);  
  6.     }  
  7.   
  8.     public void run() {  
  9.         System.out.println(Thread.currentThread().getName() + " run ");  
  10.         // 死循环,不断运行。  
  11.         while(true);  
  12.     }  
  13. }  
  14.   
  15. public class WaitTimeoutTest {  
  16.   
  17.         public static void main(String[] args) {  
  18.   
  19.         ThreadA t1 = new ThreadA("t1");  
  20.   
  21.         synchronized(t1) {  
  22.             try {  
  23.                 // 启动“线程t1”  
  24.                 System.out.println(Thread.currentThread().getName() + " start t1");  
  25.                 t1.start();  
  26.                 // 主线程等待t1通过notify()唤醒 或 notifyAll()唤醒,或超过3000ms延时;然后才被唤醒。  
  27.                 System.out.println(Thread.currentThread().getName() + " call wait ");  
  28.                 t1.wait(3000);  
  29.                 System.out.println(Thread.currentThread().getName() + " continue");  
  30.                 } catch (InterruptedException e) {  
  31.                 e.printStackTrace();  
  32.             }  
  33.         }  
  34.     }  
  35. }  
运行结果:
main start t1
main call wait
t1 run                  // 大约3秒之后...输出“main continue”
main continue

在运行t1.wait(3000),main线程会让出3秒CPU,之后会重新竞争资源。

wait()和notifyAll()方法
示例代码:
[java]  view plain  copy
  1. package test;  
  2.   
  3. public class NotifyAllTest {  
  4.   
  5. private static Object obj = new Object();  
  6.     public static void main(String[] args) {  
  7.   
  8.         ThreadA t1 = new ThreadA("t1");  
  9.         ThreadA t2 = new ThreadA("t2");  
  10.         ThreadA t3 = new ThreadA("t3");  
  11.         t1.start();  
  12.         t2.start();  
  13.         t3.start();  
  14.         try {  
  15.             System.out.println(Thread.currentThread().getName()+" sleep(3000)");  
  16.             Thread.sleep(3000);  
  17.         } catch (InterruptedException e) {  
  18.             e.printStackTrace();  
  19.         }  
  20.         synchronized(obj) {  
  21.         // 主线程等待唤醒。  
  22.         System.out.println(Thread.currentThread().getName()+" notifyAll()");  
  23.         obj.notifyAll();  
  24.         }  
  25.     }  
  26.     static class ThreadA extends Thread{  
  27.   
  28.     public ThreadA(String name){  
  29.         super(name);  
  30.     }  
  31.     public void run() {  
  32.         synchronized (obj)  
  33.             {  
  34.                 try {  
  35.                     // 打印输出结果  
  36.                     System.out.println(Thread.currentThread().getName() + " wait");  
  37.                     // 唤醒当前的wait线程  
  38.                     obj.wait();  
  39.                     // 打印输出结果  
  40.                     System.out.println(Thread.currentThread().getName() + " continue");  
  41.                     } catch (InterruptedException e) {  
  42.                     e.printStackTrace();  
  43.                     }  
  44.             }  
  45.         }  
  46.     }  
  47. }  
第一次运行结果:
t2 wait
main sleep(3000)
t1 wait
t3 wait
main notifyAll()
t3 continue
t1 continue
t2 continue
第二次运行结果:
main sleep(3000)
t2 wait
t3 wait
t1 wait
main notifyAll()
t1 continue
t3 continue
t2 continue
刚开始每个线程都运行wait将其他线程阻塞,最后main线程重新获得资源,运行notify()函数,唤醒所有的线程。

为什么notify(),wait()等函数定义在Object中,而不是Thread类中。
Object中的wait(),notify()等函数,和synchronized一样,会对对象的同步锁进行操作。wait()会使当前线程处于阻塞状态,是因为该线程进入了阻塞状态,所以线程应该释放了它拥有的同步锁,否则其他线程无法运行。wait()等待线程和notify()之间是通过什么关联起来的?答案是对象的同步锁。负责唤醒等待线程的那个线程,只有它在获取了该对象的同步锁之后,才调用notify或notify()方法之后,才能唤醒等待线程。
总之,notify(),wait()依赖于同步锁,而同步锁是对象锁持有,并且每个对象有且仅有一个,这就是为什么notify()和wait()等函数定义在object类,而不是Thread类中的原因。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值