java多线程之wait_Java多线程之wait()和notify()

package com.jadyer.thread.wait;

/**

* Java多线程之wait()和notify()的妙用

* @see =================================================================================================================

* @see 问题:同时启动两个线程和同时启动四个线程,控制台打印结果是不同的

* @see      同时启动两个线程时,控制台会很规律的输出1010101010101010

* @see      同时启动四个线程时,控制台起初会规律的输出10101010,一旦某一刻输出一个负数,那么后面的输出就会"一错再错"

* @see 分析:对线程而言,任何一种情况,都是合理的

* @see      这里假设其中的一种情况:tt22先执行,此时number=0,所以执行到了decrease()方法中的wait()方法,于是tt22被阻塞

* @see      接着tt44执行了,此时number=0,所以也执行到了decrease()方法中的wait()方法,于是tt44也被阻塞了

* @see      然后tt11执行了,此时number=0,www.linuxidc.com于是便执行到了increase()方法中的number++和notify()方法

* @see      重点在于tt11执行到notify()方法时,我们假设该方法唤醒了tt44线程,于是tt44开始执行decrease()方法中的number--

* @see      此时number=-1,然后执行到了decrease()方法中notify()方法,我们同样假设该notify()方法唤醒的是tt22线程

* @see      同样的道理,number又被减减了,于是number=-2,并被打印到控制台了,然后再假设tt22中的notify()方法唤醒的是tt11

* @see      如此的循环往复,就看到那种"一错再错"的效果了

* @see =================================================================================================================

* @see 修复:我们应当在wait()被唤醒的时候,再判断一次,然后再决定是否让该线程继续wait()下去

* @see      因为,当某个线程被唤醒时,它不知道外界在其睡眠的期间发生了神马,所以要再判断一次。所以把if()改为while()判断,即可

* @see =================================================================================================================

* @see 补充:如果只有两个线程的话,一个是对number增加的线程,一个是对number减少的线程,此时用if()判断是没有问题的

* @see      因为无论线程如何的唤醒,它所唤醒的都是另一个线程,不存在第三个线程插进来捣乱的情况

* @see =================================================================================================================

* @author 宏宇

* @create Feb 22, 2012 3:20:05 PM

*/

public  class WaitNotifyTest {

public  static  void main(String[] args) {

Count count =  new Count();

Thread tt11 =  new Thread( new IncreaseThread(count));

Thread tt22 =  new Thread( new DecreaseThread(count));

Thread tt33 =  new Thread( new IncreaseThread(count));

Thread tt44 =  new Thread( new DecreaseThread(count));

tt11.start();

tt22.start();

tt33.start();

tt44.start();

}

}

class IncreaseThread  implements Runnable{

private Count count;

public IncreaseThread(Count count){

this.count = count;

}

@Override

public  void run() {

for( int i=0; i<20; i++){

try {

Thread.sleep(( long)(Math.random()*1000));

}  catch (InterruptedException e) {

e.printStackTrace();

}

count.increase();

}

}

}

class DecreaseThread  implements Runnable{

private Count count;

public DecreaseThread(Count count){

this.count = count;

}

@Override

public  void run() {

for( int i=0; i<20; i++){

try {

Thread.sleep(( long)(Math.random()*1000));

}  catch (InterruptedException e) {

e.printStackTrace();

}

count.decrease();

}

}

}

class Count{

private  int number;

public  synchronized  void increase(){

if(0 != number){

try {

//在同步方法(或者同步语句块)中,被锁定的对象可以调用wait()方法,这将导致当前线程被阻塞并释放该对象的互斥锁

//即解除了wait()方法所对应的当前对象的锁定状态,然后,其它的线程就有机会访问该对象了

wait();

}  catch (InterruptedException e) {

e.printStackTrace();

}

}

number++;

System.out.println(number);

//唤醒其它的由于调用了wait()方法而在等待同一个对象的线程

//该方法每次运行时,只能唤醒等待队列中的一个线程,至于是哪一个线程被唤醒,则由线程调度器来决定,程序员无法控制

notify();

}

public  synchronized  void decrease(){

if(0 == number){

try {

wait();

}  catch (InterruptedException e) {

e.printStackTrace();

}

}

number--;

System.out.println(number);

notify();

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值