黑马程序员技术交流社区

标题: 运行的结果为什么不一样呢?求解! [打印本页]

作者: 小熊星座    时间: 2014-5-5 21:03
标题: 运行的结果为什么不一样呢?求解!
本帖最后由 小熊星座 于 2014-5-7 18:56 编辑

在学习同步代码块和同步函数的过程中,用它们写了同一个例子,为什么结果不一样呢?
Wo31运行的结果是100  100  200  200  300  300   ,Wo32运行的结果却是100  200  300  400  500  600  。
我哪里写错了?求帮助,给解释解释。
  1. //例子:银行有一个金库,两个储户分别存300元,每次存100,存3次。
  2. class Bank
  3. {
  4.         private int sum;
  5.         
  6.         public  synchronized void add(int n)
  7.         {
  8.                 sum=sum+n;
  9.                 try
  10.                   {
  11.                         Thread.sleep(10);
  12.                   }
  13.                  catch(Exception e)
  14.                   { }
  15.                   System.out.println(sum);
  16.                
  17.         }
  18.         
  19. }
  20. class Depositor extends Thread
  21. {
  22.     Bank b=new Bank();   
  23.         public void run()   
  24.         {
  25.                 for(int x=0;x<3;x++)
  26.                 {
  27.                         b.add(100);
  28.                 }
  29.         }
  30. }
  31. class Wo31
  32. {
  33.         public static void main(String[]args)
  34.         {
  35.                 Depositor d1=new Depositor();
  36.                 Depositor d2=new Depositor();
  37.                 d1.start();
  38.                 d2.start();
  39.                
  40.         }
  41. }
复制代码


  1. //例子:银行有一个金库,两个储户分别存300元,每次存100,存3次。
  2. class Bank
  3. {
  4.         private int sum;
  5.         Object obj=new Object();
  6.         public  void add(int n)
  7.         {
  8.                 synchronized(obj)
  9.                 {
  10.                         sum=sum+n;
  11.                
  12.                   try
  13.                   {
  14.                         Thread.sleep(10);
  15.                   }
  16.                  catch(Exception e)
  17.                   { }
  18.                   System.out.println(sum);
  19.                 }
  20.         }
  21.         
  22. }
  23. class Depositor implements Runnable
  24. {
  25.     Bank b=new Bank();
  26.         public void run()
  27.         {
  28.                 for(int x=0;x<3;x++)
  29.                 {
  30.                         b.add(100);
  31.                 }
  32.         }
  33. }
  34. class Wo32
  35. {
  36.         public static void main(String[]args)
  37.         {
  38.                 Depositor d=new Depositor();
  39.                 Thread t1=new Thread(d);
  40.                 Thread t2=new Thread(d);
  41.                 t1.start();
  42.                 t2.start();
  43.                
  44.         }
  45. }
复制代码

作者: jieyu90    时间: 2014-5-5 22:10
先来看看两个例子的区别:第一个例子里面线程类继承Thread类实现,第二个例子里面通过实现Runnable接口创建线程类。
其实区别就在这个地方,从第二个例子的输出可以看出,两个线程的Bank.sum变量是连续的,从这点你可以大胆猜想第二个例子中虽然创建了两个线程t1、t2,当时只创建了一个Bank实例,且这两个线程共享这个Bank实例。回过头来看下代码:
Thread t1=new Thread(d);
Thread t2=new Thread(d);

这种创建线程的方式实际上用到了Thread(Runnable target) 这个构造方法,此时程序所创建的Depositor对象只是线程的target,而多个线程可以共享一个target,当然t1、t2也共享线程类中的实例变量b,所以结果就像你看到的一样,而第一个例子中两个线程不共享实例变量b,balabala……

作者: 875588381    时间: 2014-5-6 08:47
第二个例子就不多说了,没什么问题。主要就是第一个例子中有一点小问题。
你创建了两个Depositor,每个Depositor中有一个成员变量Bank b,明白了吗?
相当于有两个银行,每个线程向各自的银行存钱,结果当然不对了。
希望对你有所帮助。

                Depositor d1=new Depositor();

                Depositor d2=new Depositor();

                d1.start();

                d2.start();
作者: 小熊星座    时间: 2014-5-6 23:05
875588381 发表于 2014-5-6 08:47
第二个例子就不多说了,没什么问题。主要就是第一个例子中有一点小问题。
你创建了两个Depositor,每个Depo ...

在Bank b=new Bank();前面加上static就可以了。是吧?
作者: 875588381    时间: 2014-5-7 11:12
小熊星座 发表于 2014-5-6 23:05
在Bank b=new Bank();前面加上static就可以了。是吧?

对,这样做可以。
加上了static之后,Bank b 就相当于类成员了,在类加载的时候就会被创建,它被该类的所有对象共享,而不是每个对象都会单独去创建一个。




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