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

标签: java 多线程 wait | 发表时间:2012-03-22 16:45 | 作者:hopezhangbo
出处:http://blog.csdn.net

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

  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. }  
作者:hopezhangbo 发表于2012-3-22 16:45:28 原文链接
阅读:5 评论:0 查看评论

相关 [java 多线程 wait] 推荐:

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

- - CSDN博客推荐文章
直接看测试代码吧,细节之处,详见注释.  * Java多线程之wait()和notify()的妙用 .  * @see 问题:同时启动两个线程和同时启动四个线程,控制台打印结果是不同的 .  * @see      同时启动两个线程时,控制台会很规律的输出1010101010101010 .  * @see      同时启动四个线程时,控制台起初会规律的输出10101010,一旦某一刻输出一个负数,那么后面的输出就会"一错再错" .

java多线程设计wait/notify机制

- - CSDN博客推荐文章
  当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait() , 放弃对象锁..   之后在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:.   # 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {…} 代码段内.

Java多线程之wait和notify

- - ITeye博客
最近在看Java特种兵,看到多线程部分,对wait和notify不是很理解,于是写了代码来帮助理解.              wait方法通过参数可以指定等待的时长. 如果没有指定参数,默认一直等待直到被通知. notify方法是通知某个正在等待这个对象的控制权的线程可以继续运行. 调用wait方法时候,必须加上synchronized同步块,不然会抛出java.lang.IllegalMonitorStateException异常.

Java Sleep() 与 Wait()的机制原理与区别

- - CSDN博客推荐文章
Java中的多线程是一种抢占式的机制而不是分时机制. 线程主要有以下几种状态:可运行,运行,阻塞,死亡. 抢占式机制指的是有多个线程处于可运行状态,但是只有一个线程在运行.        当有多个线程访问共享数据的时候,就需要对线程进行同步.        Thread类的方法:sleep(),yield()等.

[转载]java之yield(),sleep(),wait()区别详解

- - 移动开发 - ITeye博客
使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁. 也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据. 例如有两个线程同时执行(没有synchronized)一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有Sleep()方法,只有高优先级的线程执行完毕后,低优先级的线程才能够执行;但是高优先级的线程sleep(500)后,低优先级就有机会执行了.

Java Thread多线程

- - CSDN博客推荐文章
Java Thread多线程. Java 多线程例子1 小例子. super("zhuyong");//设置线程的名字,默认为“TestThread”. Java 多线程例子2 前台线程(用户线程) 后台线程(守护线程 ). 1,setDaemon(true)后就是后台线程(守护线程 ),反之就是前台线程(用户线程).

Java多线程之synchronized

- - CSDN博客推荐文章
这里通过三个测试类阐述了synchronized应用的不同场景. 首先是最基本的synchronized Method的使用.  * @see 概述:Java中的每个对象都有一个锁(lock)或者叫做监视器(monitor) .  * @see 说明:当synchronized关键字修饰一个方法时,则该方法为同步方法 .

java多线程总结

- - Java - 编程语言 - ITeye博客
在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口. 对于直接继承Thread的类来说,代码大致框架是:. class 类名 extends Thread{. * @author Rollen-Holt 继承Thread类,直接调用run方法.             System.out.println(name + "运行     " + i);.

Java多线程学习

- - CSDN博客编程语言推荐文章
  线程是一种轻量级的进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单. 即多个线程可以同时执行,就像有多条流水线一样,可以同时进行工作,是并发执行的.   程序是由进程组成的,进程是由线程组成的.

Java多线程(二)同步

- - CSDN博客编程语言推荐文章
如果你的java基础较弱,或者不大了解java多线程请先看这篇文章 java多线程(一)线程定义、状态和属性. 同步一直是java多线程的难点,在我们做android开发时也很少应用,但这并不是我们不熟悉同步的理由. 希望这篇文章能使更多的人能够了解并且应用java的同步. 在多线程的应用中,两个或者两个以上的线程需要共享对同一个数据的存取.