关闭

Java多线程之wait()和notify()

869人阅读 评论(0) 收藏 举报

直接看测试代码吧,细节之处,详见注释

  1. package com.jadyer.thread.wait;  
  2.   
  3. /** 
  4.  * Java多线程之wait()和notify()的妙用 
  5.  * @see ================================================================================================================= 
  6.  * @see 问题:同时启动两个线程和同时启动四个线程,控制台打印结果是不同的 
  7.  * @see      同时启动两个线程时,控制台会很规律的输出1010101010101010 
  8.  * @see      同时启动四个线程时,控制台起初会规律的输出10101010,一旦某一刻输出一个负数,那么后面的输出就会"一错再错" 
  9.  * @see 分析:对线程而言,任何一种情况,都是合理的 
  10.  * @see      这里假设其中的一种情况:tt22先执行,此时number=0,所以执行到了decrease()方法中的wait()方法,于是tt22被阻塞 
  11.  * @see      接着tt44执行了,此时number=0,所以也执行到了decrease()方法中的wait()方法,于是tt44也被阻塞了 
  12.  * @see      然后tt11执行了,此时number=0,www.linuxidc.com于是便执行到了increase()方法中的number++和notify()方法 
  13.  * @see      重点在于tt11执行到notify()方法时,我们假设该方法唤醒了tt44线程,于是tt44开始执行decrease()方法中的number-- 
  14.  * @see      此时number=-1,然后执行到了decrease()方法中notify()方法,我们同样假设该notify()方法唤醒的是tt22线程 
  15.  * @see      同样的道理,number又被减减了,于是number=-2,并被打印到控制台了,然后再假设tt22中的notify()方法唤醒的是tt11 
  16.  * @see      如此的循环往复,就看到那种"一错再错"的效果了 
  17.  * @see ================================================================================================================= 
  18.  * @see 修复:我们应当在wait()被唤醒的时候,再判断一次,然后再决定是否让该线程继续wait()下去 
  19.  * @see      因为,当某个线程被唤醒时,它不知道外界在其睡眠的期间发生了神马,所以要再判断一次。所以把if()改为while()判断,即可 
  20.  * @see ================================================================================================================= 
  21.  * @see 补充:如果只有两个线程的话,一个是对number增加的线程,一个是对number减少的线程,此时用if()判断是没有问题的 
  22.  * @see      因为无论线程如何的唤醒,它所唤醒的都是另一个线程,不存在第三个线程插进来捣乱的情况 
  23.  * @see ================================================================================================================= 
  24.  * @author 宏宇 
  25.  * @create Feb 22, 2012 3:20:05 PM 
  26.  */  
  27. public class WaitNotifyTest {  
  28.     public static void main(String[] args) {  
  29.         Count count = new Count();  
  30.           
  31.         Thread tt11 = new Thread(new IncreaseThread(count));  
  32.         Thread tt22 = new Thread(new DecreaseThread(count));  
  33.           
  34.         Thread tt33 = new Thread(new IncreaseThread(count));  
  35.         Thread tt44 = new Thread(new DecreaseThread(count));  
  36.           
  37.         tt11.start();  
  38.         tt22.start();  
  39.           
  40.         tt33.start();  
  41.         tt44.start();  
  42.     }  
  43. }  
  44.   
  45.   
  46. class IncreaseThread implements Runnable{  
  47.     private Count count;  
  48.     public IncreaseThread(Count count){  
  49.         this.count = count;  
  50.     }  
  51.     @Override  
  52.     public void run() {  
  53.         for(int i=0; i<20; i++){  
  54.             try {  
  55.                 Thread.sleep((long)(Math.random()*1000));  
  56.             } catch (InterruptedException e) {  
  57.                 e.printStackTrace();  
  58.             }  
  59.             count.increase();  
  60.         }  
  61.     }  
  62. }  
  63.   
  64.   
  65. class DecreaseThread implements Runnable{  
  66.     private Count count;  
  67.     public DecreaseThread(Count count){  
  68.         this.count = count;  
  69.     }  
  70.     @Override  
  71.     public void run() {  
  72.         for(int i=0; i<20; i++){  
  73.             try {  
  74.                 Thread.sleep((long)(Math.random()*1000));  
  75.             } catch (InterruptedException e) {  
  76.                 e.printStackTrace();  
  77.             }  
  78.             count.decrease();  
  79.         }  
  80.     }  
  81. }  
  82.   
  83.   
  84. class Count{  
  85.     private int number;  
  86.       
  87.     public synchronized void increase(){  
  88.         if(0 != number){  
  89.             try {  
  90.                 //在同步方法(或者同步语句块)中,被锁定的对象可以调用wait()方法,这将导致当前线程被阻塞并释放该对象的互斥锁   
  91.                 //即解除了wait()方法所对应的当前对象的锁定状态,然后,其它的线程就有机会访问该对象了   
  92.                 wait();  
  93.             } catch (InterruptedException e) {  
  94.                 e.printStackTrace();  
  95.             }  
  96.         }  
  97.         number++;  
  98.         System.out.println(number);  
  99.         //唤醒其它的由于调用了wait()方法而在等待同一个对象的线程   
  100.         //该方法每次运行时,只能唤醒等待队列中的一个线程,至于是哪一个线程被唤醒,则由线程调度器来决定,程序员无法控制   
  101.         notify();  
  102.     }  
  103.       
  104.     public synchronized void decrease(){  
  105.         if(0 == number){  
  106.             try {  
  107.                 wait();  
  108.             } catch (InterruptedException e) {  
  109.                 e.printStackTrace();  
  110.             }  
  111.         }  
  112.         number--;  
  113.         System.out.println(number);  
  114.         notify();  
  115.     }  
  116. }  
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:270032次
    • 积分:4820
    • 等级:
    • 排名:第5961名
    • 原创:201篇
    • 转载:19篇
    • 译文:2篇
    • 评论:33条
    文章分类
    最新评论