黑马程序员技术交流社区

标题: 线程wait, notify 达不到效果,不理解 [打印本页]

作者: 冷漠无天    时间: 2013-11-21 09:50
标题: 线程wait, notify 达不到效果,不理解
为什么下面例子只输出:
print
---save
---save存入2000
sleep
xingle

例子:
package zhang11_Thread;
import java.util.concurrent.locks.ReentrantLock;
public class WaitNotifyTest {
public static void main(String[] args) {

  ATMZhanghu atm = new ATMZhanghu("ATM",0);
  SavePerson savep = new SavePerson(atm,2000);
  PrintPerson printp = new PrintPerson(atm,2000);
  Thread tp = new Thread(printp,"print");
  Thread ts = new Thread(savep,"---save");
  tp.start();
  ts.start();
}
}
class ATMZhanghu{

private final ReentrantLock lock = new ReentrantLock();
private String name;
private int money;
private boolean falg = false;

public ATMZhanghu(String name,int money){
  this.money = money;
  this.name = name;
}

public synchronized void PrintMon(int printm) throws InterruptedException{
  if(falg == true){

    if(printm <= money){

     System.out.println(Thread.currentThread().getName()+"取出"+printm);
     System.out.println("sleep");
//     Thread.sleep(1000);
     System.out.println("xingle");
     money -= printm;
    }else{
     System.out.println("钱不够");
    }
    System.out.println("余额:"+ money);
   falg = false;
   notifyAll();
  }else{
   wait();
  }
}
public synchronized void SaveMon(int savem) throws InterruptedException{

  if(falg == true){
   wait();
  }else{

    System.out.println(Thread.currentThread().getName()+"存入"+savem);
    System.out.println("sleep");
//    Thread.sleep(1000);
    System.out.println("xingle");
    this.money +=savem;
    falg = true;
    notifyAll();
  }
}
public ReentrantLock getLock() {
  return lock;
}
public String getName() {
  return name;
}
public int getMoney() {
  return money;
}
public boolean isFalg() {
  return falg;
}
}
class SavePerson implements Runnable{
private ATMZhanghu atmz;
private int savem;
public SavePerson(ATMZhanghu atm,int m){
  this.atmz = atm;
  this.savem = m;
}
public void run(){
   System.out.println(Thread.currentThread().getName() + " " );
   try {
    atmz.SaveMon(savem);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
}
}
class PrintPerson implements Runnable{
private ATMZhanghu atmz;
private int printm;
public PrintPerson(ATMZhanghu atm,int m){
  this.atmz = atm;
  this.printm = m;
}
public void run(){
   System.out.println(Thread.currentThread().getName() + " " );
   try {
    atmz.PrintMon(printm);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
}
}

作者: ysunday    时间: 2013-11-21 11:41
首先,你的代码很乱,尽量用工具栏中的<>
这个东西来贴代码,格式会好点。
然后
public synchronized void PrintMon(int printm) throws InterruptedException {
        if (falg != true) {

我不缺定你这个flag是来标识什么的,我这边flag==true表示正在操作atm,否则不在操作
所以我把取钱的代码改成了if(flag != true)就是说,假如没有在操作
我才取钱,否则wait()
  1. public synchronized void PrintMon(int printm) throws InterruptedException {
  2.                 if (falg != true) {

  3.                         if (printm <= money) {

  4.                                 System.out.println(Thread.currentThread().getName() + "取出"
  5.                                                 + printm);
  6.                                 System.out.println("sleep");
  7.                                  Thread.sleep(1000);
  8.                                 System.out.println("xingle");
  9.                                 money -= printm;
  10.                         } else {
  11.                                 System.out.println("钱不够");
  12.                         }
  13.                         System.out.println("余额:" + money);
  14.                         falg = false;  //这里我把falg置成false,表示取钱完毕
  15.                         notifyAll();
  16.                 } else {
  17.                         wait();
  18.                 }
  19.         }

  20. 还有就是每次取完钱应该把标志置为false,表示取完了,没有人在操作取款机了


  21. 当改正了上边两处错误之后,起码你每次取钱和存钱都会有对应的输出了,不会只有
  22. 你陈述的那个输出了

  23. 2.线程的启动是有随机性的,虽然你先启动的取钱,但是有可能存钱线程启动之后
  24. 会抢占cpu执行,先执行完了存钱,也有可能先执行完取钱,这是不确定的

  25. 情况一:取钱先执行了

  26. 那么取钱的时候还没钱,就会输出没钱
  27. 然后执行存钱,正常输出存钱
  28. 执行结果如下

  29. print
  30. 钱不够
  31. 余额:0
  32. ---save
  33. ---save存入2000
  34. sleep
  35. xingle

  36. 情况二;先执行完的存钱,正常输出存钱,
  37. 那么取钱再执行的时候就能正常取钱了,也正常输出
  38. 结果如下
  39. ---save
  40. print
  41. ---save存入2000
  42. sleep
  43. xingle
  44. print取出2000
  45. sleep
  46. xingle
  47. 余额:0


  48. 这个因为随机性很强,多运行几次就出结果了
复制代码





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2