黑马程序员技术交流社区

标题: 关于多线程的问题,求解惑。 [打印本页]

作者: 刘亚东    时间: 2014-8-1 15:36
标题: 关于多线程的问题,求解惑。
本帖最后由 刘亚东 于 2014-8-1 15:37 编辑

看视频多线程里有一个关于售票的练习。
毕老师说用继承方式创建线程对象,每个对象都有100张票可以卖,所以可以把票的变量tick用static修饰是一种解决办法,但是一般不用这种办法,
后来改用了实现方式来创建线程对象,也没用static修饰tick变量,为什么四个线程就能共享100张票呢?
代码如下:
  1. <p>class Ticket implements Runnable//创建一个类实现Runnable接口
  2. {
  3.         private int tick = 100;//定义一个变量tick,表示可以卖的票
  4.         public void run()//run方法用来存放线程要执行的代码
  5.         {
  6.                 while (true)
  7.                 {
  8.                         if (tick>0)
  9.                         {
  10.                                 System.out.println(Thread.currentThread().getName()+"...sale : "+ tick--);
  11.                         }
  12.                 }

  13.         }
  14. }

  15. class TicketDemo2
  16. {
  17.         public static void main(String[] args)
  18.         {
  19.                
  20.                 Ticket t = new Ticket();//创建一个对象</p><p> </p><p>//创建四个线程</p><p>Thread t1 = new Thread(t);
  21.                 Thread t2 = new Thread(t);
  22.                 Thread t3 = new Thread(t);
  23.                 Thread t4 = new Thread(t);</p><p> </p><p>//启动线程并执行run方法
  24. t1.start();
  25. t2.start();
  26. t3.start();
  27. t4.start();
  28.         }
  29. }</p>
复制代码
代码执行的结果是四个线程一共出售100张票。

之前的代码:
  1. <p>class Ticket extends Thread
  2. {
  3. private int tick = 100;//此处如果不加static,那么代码执行时,每个线程都会出售100张票。
  4. public void run ()
  5. {
  6.   while (true)
  7.   {
  8.    if (tick>0)
  9.    {
  10.     System.out.println(Thread.currentThread().getName()+"...sale : "+ tick--);
  11.    }
  12.   }</p><p> }
  13. }</p><p>class TicketDemo
  14. {
  15. public static void main(String[] args)
  16. {
  17.   
  18.   Ticket t1 = new Ticket();
  19.   Ticket t2 = new Ticket();
  20.   Ticket t3 = new Ticket();
  21.   Ticket t4 = new Ticket();</p><p>  t1.start();
  22.   t2.start();
  23.   t3.start();
  24.   t4.start();
  25. }
  26. }
复制代码

上、下两段代码的什么区别造成了这样的结果?
为什么第一段代码可以四个线程同时一共出售100张票?


作者: 李彦来    时间: 2014-8-1 16:53
因为,一个是实现Runnable,一个是继承Thread
第一段代码只new了一个Ticket,内存中只有1个Ticket对象,所以是100张票,是四个线程去调用它,

第二段代码new了四次,说明内存中有4个Ticket对象,所以是4个100张票,是四个线程调用四个Ticket对象,
作者: 吴杰栋    时间: 2014-8-1 17:14
继承Thread的时候,Ticket t1 = new Ticket();
                          Ticket t2 = new Ticket();
                          Ticket t3 = new Ticket();
                          Ticket t4 = new Ticket() 就产生了四个对象(400张票)了
而实现Runnable接口的时候Ticket t = new Ticket()只有100张票
                Thread t1 = new Thread(t);
                Thread t2 = new Thread(t);
                Thread t3 = new Thread(t);
                Thread t4 = new Thread(t)然后分给4个人用,所以就只会买100张票
作者: yqj    时间: 2014-8-1 17:30
本帖最后由 yqj 于 2014-8-1 17:56 编辑

1.对于继承时加static修饰tick变量,四个线程就能共享100张票的原因
    static 关键字的作用:被static修饰的成员变量和成员方法独立于该类(可以理解为Ticket类)的任何对象(可以理解为Ticket t=new Ticket();中的t对象)。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象(百科)。
    我的理解是,当tick前加了static关键字时,tick变量将在Ticket类被加载的时候被创建,以后在每次new Ticket()时,Ticket类的对象的tick变量将都指向Ticket类加载时创建的tick的内存区域,也就说
  Ticket t1 = new Ticket();
  Ticket t2 = new Ticket();
  Ticket t3 = new Ticket();
  Ticket t4 = new Ticket();t1,t2,t3,t4指向是同一个tick变量,即四个线程都是操作同一个tick变量,所以所以四个线程就能共享100张票对于tick变量未加static时t1,t2,t3,t4每个对象将都有一个自己的tick变量,每个线程将各买各的票,所以会出现 打印显示 同一个票被买四次的情况
2.对于实现Runnable时,线程就能共享100张票的原因Ticket t = new Ticket();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        Thread t3 = new Thread(t);
        Thread t4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();

四个线程都是调用的同一个对象(t对象)的run方法,所以四个线程都是操作的同一个对象的tick变量,即四个线程都是操作同一个tick变量,所以所以所以四个线程就能共享100张票

希望我的回答对楼主有用!



作者: Wokno    时间: 2014-8-1 21:34
楼上说了那么多,其实楼主直接去看看API文档一切都解决了。。。。。。。
作者: 咸菜+萝卜干    时间: 2014-8-2 01:26
兄弟,你这个问题其实跟多线程没多大关系,第一段代码Tieket类new了一次,当然只有100张,第二段代码Ticket类new了4次,当然就是400张,还是基础啊基础啊兄弟!{:3_47:}
作者: AuroraAria    时间: 2014-8-2 10:12
第一段代码才算是真正想要的多线程,四个线程在共享一个对象的数据,而对象的tick只有100,所以一共卖出100。
第二段代码应该算是“伪多线程”,虽然是四个线程在一起运行,但是线程之间根本没有联系,每个线程对应一个对象,每个对象tick是100。只不过四个线程在交替执行而已。所以就不难得出每个线程卖100张票,一共400的结果。
作者: 刘亚东    时间: 2014-8-2 17:36
李彦来 发表于 2014-8-1 16:53
因为,一个是实现Runnable,一个是继承Thread
第一段代码只new了一个Ticket,内存中只有1个Ticket对象,所以是1 ...

明白了!多谢!
作者: 刘亚东    时间: 2014-8-2 17:37
吴杰栋 发表于 2014-8-1 17:14
继承Thread的时候,Ticket t1 = new Ticket();
                          Ticket t2 = new Ticket();
      ...

明白了!多谢!
作者: 刘亚东    时间: 2014-8-2 17:40
yqj 发表于 2014-8-1 17:30
1.对于继承时加static修饰tick变量,四个线程就能共享100张票的原因
    static 关键字的作用:被static修 ...

讲的很详细,多谢。
作者: 刘亚东    时间: 2014-8-2 17:41
AuroraAria 发表于 2014-8-2 10:12
第一段代码才算是真正想要的多线程,四个线程在共享一个对象的数据,而对象的tick只有100,所以一共卖出100 ...

原来如此!多谢!
作者: 沟门大杏    时间: 2014-8-4 12:03
加了同步代码块。static就可以不用了
作者: zeus00456    时间: 2014-8-4 19:20
我感觉这个问题有一种简单的解释方式
票的数量是类Ticket中的成员变量,当我new一个对象时,我们有了100张票

但是你看毕老师的代码,票的对象只有一个,只有100张票,
开线程时,每一个线程都使用的是这个唯一的Ticket对象,也就相当于4个人一起卖100张票了
作者: wangyang    时间: 2014-8-4 23:08
看了这么多高手的回复,我也明白了
作者: 冒牌高手    时间: 2014-8-5 14:50
因为下面new了四个,每一个都有100张票,所以是400




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