A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 李贺晓 中级黑马   /  2012-11-21 14:17  /  5156 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

//定义银行账户
class  Account
{
private String accountnum;
private double money;
private boolean flag=false;
Account(String accountnum,double money)
{
  this.accountnum=accountnum;
  this.money=money;
}
public void setAccountnum(String accountnum)
{
  this.accountnum=accountnum;
}
public String getAccountnum()
{
  return accountnum;
}
public double getMoney()
{
  return this.money;
}
public int hashCode()
{
  return accountnum.hashCode();
}
public boolean equals(Object obj)
{
  if(obj!=null && obj.getClass()==Account.class)
  {
   Account a=(Account) obj;
   return a.getAccountnum().equals(accountnum);
  }
  return false;
}
public synchronized void pullMoney(double pullmoney)
{
  
   try
   {
    if(!flag)
    {
     wait();
    }
    else
    {
     System.out.print(Thread.currentThread().getName()+"取钱:"+pullmoney);
     money=money-pullmoney;
     System.out.println(",账户余额为:"+money);
     flag=false;
     notifyAll();
    }
   }
   catch (InterruptedException e)
   {
    e.printStackTrace();
   }
   
}
public synchronized void pushMoney(double pushmoney)
{
  try
  {
   if(flag)
   {
    wait();
   }
   else
   {
    System.out.print(Thread.currentThread().getName()+"存钱:"+pushmoney);
    money=money+pushmoney;
    System.out.println(",账户余额为:"+money);
    flag=true;
    notifyAll();
   }
  }
  catch (InterruptedException e)
  {
   e.printStackTrace();
  }
}

}
class PullThread extends Thread
{
private Account account;
private double pullmoney;
PullThread(){}
PullThread(String name,Account account,double pullmoney)
{
  super(name);
  this.account=account;
  this.pullmoney=pullmoney;
}
public void run()
{
  for(int i=0;i<10;i++)
  {
   account.pullMoney(pullmoney);
  }
}
}
class PushThread extends Thread
{
private Account account;
private double pushmoney;
PushThread(String name,Account account,double pushmoney)
{
  super(name);
  this.account=account;
  this.pushmoney=pushmoney;
}
public void run()
{
  for(int i=0;i<10;i++)
  {
   account.pushMoney(pushmoney);
  }
}
}
class Test2
{
public static void main(String[] args)
{
  Account a=new Account("123456",0);
  PullThread p=new PullThread("甲取钱",a,500);
  p.start();
  PushThread p1=new PushThread("已存钱",a,500);
  
  p1.start();
  
}
}
我设置的是存钱取钱个10次,但是运行后,为什么是存钱取钱各5次啊?
是哪里出的问题,求解答

评分

参与人数 1技术分 +1 收起 理由
古银平 + 1 神马都是浮云

查看全部评分

4 个回复

正序浏览
应为当wait()线程被唤醒后,这个线程没什么要做的就直接结束了,所以只打印出5次。你在wait()后面加上
  1. System.out.print(Thread.currentThread().getName() + "取钱:"
  2.                                                 + pullmoney);
  3.                                 money = money - pullmoney;
  4.                                 System.out.println(",账户余额为:" + money);
  5.                                 flag = false;
复制代码
段代码就能打印10次
  1. class Account {
  2.         private String accountnum;
  3.         private double money;
  4.         private boolean flag = false;

  5.         Account(String accountnum, double money) {
  6.                 this.accountnum = accountnum;
  7.                 this.money = money;
  8.         }

  9.         public void setAccountnum(String accountnum) {
  10.                 this.accountnum = accountnum;
  11.         }

  12.         public String getAccountnum() {
  13.                 return accountnum;
  14.         }

  15.         public double getMoney() {
  16.                 return this.money;
  17.         }

  18.         public int hashCode() {
  19.                 return accountnum.hashCode();
  20.         }

  21.         public boolean equals(Object obj) {
  22.                 if (obj != null && obj.getClass() == Account.class) {
  23.                         Account a = (Account) obj;
  24.                         return a.getAccountnum().equals(accountnum);
  25.                 }
  26.                 return false;
  27.         }

  28.         public synchronized void pullMoney(double pullmoney) {

  29.                 try {
  30.                         if (!flag) {
  31.                                 System.out.println("取钱等待");
  32.                                 wait();
  33.                                 //线程被唤醒后要做的事
  34.                                 System.out.println("取钱激活");
  35.                                 System.out.print(Thread.currentThread().getName() + "取钱:"
  36.                                                 + pullmoney);
  37.                                 money = money - pullmoney;
  38.                                 System.out.println(",账户余额为:" + money);
  39.                                 flag = false;
  40.                        
  41.                         } else {
  42.                                 System.out.print(Thread.currentThread().getName() + "取钱:"
  43.                                                 + pullmoney);
  44.                                 money = money - pullmoney;
  45.                                 System.out.println(",账户余额为:" + money);
  46.                                 flag = false;
  47.                                 notifyAll();
  48.                         }
  49.                 } catch (InterruptedException e) {
  50.                         e.printStackTrace();
  51.                 }

  52.         }

  53.         public synchronized void pushMoney(double pushmoney) {
  54.                 try {
  55.                         if (flag) {
  56.                                 wait();
  57.                                 //线程被唤醒后要做的事
  58.                                 System.out.print(Thread.currentThread().getName() + "存钱:"
  59.                                                 + pushmoney);
  60.                                 money = money + pushmoney;
  61.                                 System.out.println(",账户余额为:" + money);
  62.                                 flag = true;
  63.                         } else {
  64.                                 System.out.print(Thread.currentThread().getName() + "存钱:"
  65.                                                 + pushmoney);
  66.                                 money = money + pushmoney;
  67.                                 System.out.println(",账户余额为:" + money);
  68.                                 flag = true;
  69.                                 notifyAll();
  70.                         }
  71.                 } catch (InterruptedException e) {
  72.                         e.printStackTrace();
  73.                 }
  74.         }

  75. }

  76. class PullThread extends Thread {
  77.         private Account account;
  78.         private double pullmoney;

  79.         PullThread() {
  80.         }

  81.         PullThread(String name, Account account, double pullmoney) {
  82.                 super(name);
  83.                 this.account = account;
  84.                 this.pullmoney = pullmoney;
  85.         }

  86.         public void run() {
  87.                 for (int j = 0; j < 10; j++) {
  88.                         account.pullMoney(pullmoney);
  89.                         System.out.println("----"+Thread.currentThread().getName().toString());
  90.                 }
  91.         }
  92. }

  93. class PushThread extends Thread {
  94.         private Account account;
  95.         private double pushmoney;

  96.         PushThread(String name, Account account, double pushmoney) {
  97.                 super(name);
  98.                 this.account = account;
  99.                 this.pushmoney = pushmoney;
  100.         }

  101.         public void run() {
  102.                 for (int i = 0; i < 10; i++) {
  103.                         account.pushMoney(pushmoney);
  104.                         System.out.println("----"+Thread.currentThread().getName());
  105.                 }
  106.         }
  107. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
廖力 发表于 2012-11-21 19:03
在你的run方法中分别加入和打印的结果是
pull 0
push 0

嗯,你这种方法是不错,但是我按照我写的应该也是没问题的啊,也没有造成死锁,但是就是不知道为什么只能存钱取钱各5次,不知道是怎么回事
回复 使用道具 举报
本帖最后由 廖力 于 2012-11-21 19:05 编辑

在你的run方法中分别加入
  1. System.out.println("push " + i);
复制代码
  1. System.out.println("pull " + i);
复制代码
打印的结果是
pull 0
push 0
已存钱存钱:500.0,账户余额为:500.0
push 1
甲取钱取钱:500.0,账户余额为:0.0
pull 1
push 2
已存钱存钱:500.0,账户余额为:500.0
push 3
pull 2
甲取钱取钱:500.0,账户余额为:0.0
pull 3
push 4
已存钱存钱:500.0,账户余额为:500.0
push 5
pull 4
甲取钱取钱:500.0,账户余额为:0.0
pull 5
push 6
已存钱存钱:500.0,账户余额为:500.0
push 7
pull 6
甲取钱取钱:500.0,账户余额为:0.0
pull 7
push 8
已存钱存钱:500.0,账户余额为:500.0
push 9
pull 8
甲取钱取钱:500.0,账户余额为:0.0
pull 9


具体原因我也不知道为什么
但是最好把wait sleep直接放在run方法里面
还有notifyAll尽量少用 因为容易出先java.lang.IllegalMonitorStateException的异常
下面是我改的 不知道你是不是这个意思...
  1. package com.test5;

  2. //定义银行账户
  3. class Account {
  4.         private String accountnum;
  5.         private double money;

  6.         Account(String accountnum, double money) {
  7.                 this.accountnum = accountnum;
  8.                 this.money = money;
  9.         }

  10.         public void setAccountnum(String accountnum) {
  11.                 this.accountnum = accountnum;
  12.         }

  13.         public String getAccountnum() {
  14.                 return accountnum;
  15.         }

  16.         public double getMoney() {
  17.                 return this.money;
  18.         }

  19.         public int hashCode() {
  20.                 return accountnum.hashCode();
  21.         }

  22.         public boolean equals(Object obj) {
  23.                 if (obj != null && obj.getClass() == Account.class) {
  24.                         Account a = (Account) obj;
  25.                         return a.getAccountnum().equals(accountnum);
  26.                 }
  27.                 return false;
  28.         }

  29.         public synchronized void pullMoney(double pullmoney) {
  30.                 System.out.print(Thread.currentThread().getName() + "取钱:" + pullmoney);
  31.                 money = money - pullmoney;
  32.                 System.out.println(",账户余额为:" + money);
  33.         }

  34.         public synchronized void pushMoney(double pushmoney) {
  35.                 System.out.print(Thread.currentThread().getName() + "存钱:" + pushmoney);
  36.                 money = money + pushmoney;
  37.                 System.out.println(",账户余额为:" + money);
  38.         }
  39. }

  40. class PullThread extends Thread {
  41.         private Account account;
  42.         private double pullmoney;

  43.         PullThread(String name, Account account, double pullmoney) {
  44.                 super(name);
  45.                 this.account = account;
  46.                 this.pullmoney = pullmoney;
  47.         }

  48.         public void run() {
  49.                 for (int i = 0; i < 10;) {
  50.                         if (account.getMoney() >= pullmoney) {
  51.                                 account.pullMoney(pullmoney);
  52.                                 i++;
  53.                                 long time = System.currentTimeMillis();
  54.                                 try {
  55.                                         Thread.sleep(333);
  56.                                 } catch (InterruptedException e) {
  57.                                         e.printStackTrace();
  58.                                 }
  59.                                 time = System.currentTimeMillis() - time;
  60.                                 System.out.println("第" + i + "次取钱耗时" + time + "毫秒");
  61.                         } else {
  62.                                 synchronized (this) {
  63.                                         try {
  64.                                                 wait();
  65.                                         } catch (InterruptedException e) {
  66.                                                 e.printStackTrace();
  67.                                         }
  68.                                 }
  69.                         }
  70.                 }
  71.         }
  72. }

  73. class PushThread extends Thread {
  74.         private Account account;
  75.         private double pushmoney;
  76.         private PullThread pt;

  77.         public void setPt(PullThread pt) {
  78.                 this.pt = pt;
  79.         }

  80.         PushThread(String name, Account account, double pushmoney) {
  81.                 super(name);
  82.                 this.account = account;
  83.                 this.pushmoney = pushmoney;
  84.         }

  85.         public void run() {
  86.                 for (int i = 0; i < 10; i++) {
  87.                         account.pushMoney(pushmoney);
  88.                         long time = System.currentTimeMillis();
  89.                         try {
  90.                                 Thread.sleep(1000);
  91.                         } catch (InterruptedException e) {
  92.                                 e.printStackTrace();
  93.                         }
  94.                         time = System.currentTimeMillis() - time;
  95.                         System.out.println("第" + i + "次存钱耗时" + time + "毫秒");
  96.                         synchronized (pt) {
  97.                                 pt.notify();
  98.                         }

  99.                 }
  100.         }
  101. }

  102. public class Test2 {
  103.         public static void main(String[] args) {
  104.                 Account a = new Account("123456", 0);
  105.                 PushThread p1 = new PushThread("乙存钱", a, 500);
  106.                 PullThread p2 = new PullThread("甲取钱", a, 500);
  107.                 p1.setPt(p2);
  108.                 p1.start();
  109.                 p2.start();

  110.         }
  111. }
复制代码
~


评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
{:soso_e101:}怎么没人解答下
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马