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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 香草芭芙 中级黑马   /  2014-10-9 13:00  /  1928 人查看  /  13 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 香草芭芙 于 2014-10-10 05:57 编辑

需求:
* 银行里有一个金库
* 有两个储户分别存300元, 每次存100, 存3次

金库用 内部类, 银行用 饿汉式。 储户class 里有 存钱方法,  参数:  存钱次数, 每次存的金额,
储户存钱用 多线程.  最后打印, 总金额,
  1. /*
  2. * 需求:
  3. * 银行有一个金库
  4. * 有两个储户分别存300元, 每次存100, 存3次
  5. *  `
  6. * 金库用 内部类, 银行用 饿汉式。 储户class 里有 存钱方法,  参数:  存钱次数, 每次存的金额,
  7. * 储户存钱用 多线程.  最后打印, 总金额,  
  8. *  
  9. * */
  10. class BankDemoTest
  11. {
  12.         public static void main(String[] args) throws InterruptedException
  13.         {
  14.                 Client cl1 = new Client(100, 3);
  15.                 Client cl2 = new Client(100, 3);
  16.                 Thread t1 = new Thread(cl1);
  17.                 Thread t2 = new Thread(cl2);
  18.                 t1.start();
  19.                 t2.start();
  20.                 /*
  21.                 while (true)
  22.                 {
  23.                         if (!(t1.isAlive() || t2.isAlive()))
  24.                         {
  25.                                 break;
  26.                         }
  27.                 }
  28.                 */
  29.                 t1.join();
  30.                 t2.join();
  31.                 System.out.println(Bank.coffer.sum);
  32.         }
  33. }
  34. class Bank
  35. {
  36.         private Bank()
  37.         {
  38.         }
  39.         static Bank b = new Bank();
  40.         static Bank getBank()
  41.         {
  42.                 return b;
  43.         }
  44.         static class coffer
  45.         {
  46.                 static int sum;
  47.         }
  48.         void add(int money)
  49.         {
  50.                 coffer.sum += money;
  51.         }
  52. }
  53. class Client implements Runnable
  54. {
  55.         Bank b = Bank.getBank();
  56.         int n;
  57.         int money;
  58.         Client(int money, int n)
  59.         {
  60.                 this.money = money;
  61.                 this.n = n;
  62.         }
  63.         void keepMoney()
  64.         {
  65.                 b.add(money);
  66.         }
  67.         @Override
  68.         public void run()
  69.         {
  70.                 // TODO Auto-generated method stub
  71.                 for (int x = 0; x < n; x++)
  72.                 {
  73.                         keepMoney();
  74.                 }
  75.         }
  76. }
复制代码



评分

参与人数 1技术分 +2 收起 理由
杨佳名 + 2 前方道路是曲折的,加油!

查看全部评分

13 个回复

倒序浏览
二楼占楼. 冲妹子头像, 相信妹子的这个问题会有好多好汉做答, 我就不献丑了. :lol
回复 使用道具 举报
  1. /*
  2. * 需求:
  3. * 银行有一个金库
  4. * 有两个储户分别存300元, 每次存100, 存3次
  5. *  `
  6. * 金库用 内部类, 银行用 饿汉式。 储户class 里有 存钱方法,  参数:  存钱次数, 每次存的金额,
  7. * 储户存钱用 多线程.  最后打印, 总金额,  
  8. *  
  9. * */
  10. class BankDemoTest
  11. {
  12.         public static void main(String[] args)
  13.         {
  14.                 Client cl1 = new Client(100, 3);
  15.                 Client cl2 = new Client(100, 3);
  16.                 Thread t1 = new Thread(cl1);
  17.                 Thread t2 = new Thread(cl2);
  18.                 t1.start();
  19.                 t2.start();
  20.                 int temp = Bank.coffer.sum;
  21.                 System.out.println(temp);
  22.         }
  23. }
  24. class Bank
  25. {
  26.         private Bank()
  27.         {
  28.         }
  29.         static Bank b = new Bank();
  30.         static Bank getBank()
  31.         {
  32.                 return b;
  33.         }
  34.         static class coffer
  35.         {
  36.                 static int sum;
  37.         }
  38.         void add(int money)
  39.         {
  40.                 coffer.sum += money;
  41.         }
  42. }
  43. class Client implements Runnable
  44. {
  45.         Bank b = Bank.getBank();
  46.         int n;
  47.         int money;
  48.         Client(int money, int n)
  49.         {
  50.                 this.money = money;
  51.                 this.n = n;
  52.         }
  53.         void keepMoney()
  54.         {
  55.                 b.add(money);
  56.         }
  57.         @Override
  58.         public void run()
  59.         {
  60.                 // TODO Auto-generated method stub
  61.                 for (int x = 0; x < n; x++)
  62.                 {
  63.                         keepMoney();
  64.                 }
  65.         }
  66. }
复制代码


为什么每次答案都不一样呢? 结果600是对的,可是结果有0,400,300,600 怎么回事。
回复 使用道具 举报
因为CPU是在多个线程之间来回切换执行。所以主线程执行打印动作的时候,其他两个线程执行到哪一步是不确定的,所以打印结果有很多。
回复 使用道具 举报
得判断线程 存在与否 再打印???
回复 使用道具 举报
香草芭芙 发表于 2014-10-9 13:57
得判断线程 存在与否 再打印???

试试用方法 isAlive() 判断线程是否存活,然后再输出总钱数
回复 使用道具 举报
D.reamJA 发表于 2014-10-9 17:10
试试用方法 isAlive() 判断线程是否存活,然后再输出总钱数

还是0, 或者600 , 没找到具体原因, 不过谢谢, 是个思路, 我重新写吧.
回复 使用道具 举报
继续加油
回复 使用道具 举报
x564573138 来自手机 中级黑马 2014-10-9 18:04:06
9#
沙发。,。。。。
回复 使用道具 举报
可以将主线程sleep几秒,等待子线程执行完毕
回复 使用道具 举报
int temp = Bank.coffer.sum;
                System.out.println(temp);
问题出在这,  给普通变量 赋 静态变量的值 好像会出问题,   改成  System.out.println(Bank.coffer.sum);
就没再出现 0了, 都是600,  为什么呢?:L
回复 使用道具 举报
香草芭芙 发表于 2014-10-9 19:54
int temp = Bank.coffer.sum;
                System.out.println(temp);
问题出在这,  给普通变量 赋 静 ...

楼主,我复制了你的代码,运行了很多次,按照你最后一个写法,有0,有300,有600其根本原因不是赋值得问题,请听我一言:
  1. t1.start();
  2.                 t2.start();
  3.                  //   int temp = Bank.coffer.sum;
  4.                 System.out.println(Bank.coffer.sum);
复制代码
t1.start()只表示该线程有了CPU的执行权,但并不表示线程已经开始执行(注:一旦线程启动,便处于Active状态,所以不可用Thread.isActive()方法)
现在加入t1,t2皆已启动,但CPU执行权仍然在main线程里面,他会执行最后的打印,虽然随后t1,t2会陆续执行,算出最终的sum值。
至于出现300就是其中一个线程执行完后,打印出结果
600...你应该已经猜到了,所以这样打印是不行(小弟我也想了很久,怎样在主线程里判断t1,t2已经执行玩了,然后打印)
你的问题:因为是两个客户通知往一个金库存钱,即存钱的方法应该同步(这个你往后学就应该知道)
我想出的一个解决方法:
该办法并不完美,因为线程一共有这样几个状态:NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED
你new一个线程后,线程便是NEW状态,当期start()后,便是后面中的一种(除去TERMINATED)
当线程结束后,便是TERMINATED状态,我便在主线程进行检测
  1. while((t1.getState().toString().equals("TERMINATED"))&&(t2.getState().toString().equals("TERMINATED")))
  2.            {
  3.                     //System.out.println(t1.getState());
  4.                     //System.out.println(t2.getState());
  5.                   System.out.println(b.total+"...............");
  6.                Thread.currentThread().sleep(1000);
  7.             System.exit(0);
复制代码
如果两个线程都已经结束,那么都应该是TERMINATED状态,但实际测试的时候,有时候什么都没输出,但有输出一定是600
至于更好的方法,正在想办法





评分

参与人数 1技术分 +1 收起 理由
杨佳名 + 1

查看全部评分

回复 使用道具 举报 1 0
hollywood2014 发表于 2014-10-9 20:48
楼主,我复制了你的代码,运行了很多次,按照你最后一个写法,有0,有300,有600其根本原因不是赋值得问 ...

感谢, 热心的回答.:)
  1. while (true)
  2.                 {
  3.                         if (!(t1.isAlive() || t2.isAlive()))
  4.                         {
  5.                                 break;
  6.                         }
  7.                 }
  8.                 System.out.println(Bank.coffer.sum);
复制代码

这是我的办法,  只是控制台打印有点延迟, 不是很满意, 再次感谢.
回复 使用道具 举报
join() 方法. 完美解决.
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马