多线程的卖票示例来理解两种创建线程方法的区别

class Ticket implements Runnable{
    private int num=100;//售票数一百张
    
    public void run() 
    {
             while(true)
           {
              if(num>0)
              {
                   System.out.println(Thread.currentThread().getName()+"...."+num--);
               }
           }
        
    }
}
public class Ticket_Demo {
    public static void main(String[] args) {
        Ticket train=new Ticket();//火车票
        Ticket HighSpeedRail=new Ticket();//高铁票
        /**
         * 创建线程,运行的是同一对象a的run方法(同一任务,卖的是同一种票)
         */
        Thread b=new Thread(train);
        Thread c=new Thread(train);
        Thread d=new Thread(train);
        
        Thread e=new Thread(HighSpeedRail);
        
        b.start();
        c.start();
        d.start();
        e.start();
        
        
    }
}

此卖票程序的最终实现功能为:多个人卖同一张票

首先,我们看第一种:实现Runnable接口的方法

    先解释一下程序,Ticket类实现Runnable接口,Runnable接口只有一个run方法(自行查阅API文档),run方法里面写的就是封装的任务代码---当while为true,循环不间断,设置了一个if条件判断:当票数>0,票数减少(否则会出现负数,这个与现实不符合),在main方法中创建一个Ticket类对象,这时候就能访问run()方法,但是此run方法并不是线程中的run方法,它只是子类覆盖(实现接口,又叫重写)的run方法,如果让train调用自身的run方法,不过是主线程开启(在一个程序中可以确认的两条线程为:主线程main和垃圾回收线程).

    接着创建Thread线程对象,new Thread();[管理的是Thread类中的成员方法,把thread类比作一个学生的话,thread对象就是其中具体的一个人,比如小明,类拥有的成员方法可以理解为学生拥有的能力,比如学习,所以说对象new什么类就是获取其中的能力],此时b,c,d就拥有了Thread的start()[开启线程的能力,具体它开启哪个线程就看里面传的参数对象].这里我们有必要了解:以实现Runnable接口这种创建线程方法的运行细节和Thread类的一个构造方法

 


 

 

/**
 * 多线程实现细节
 * 
 * 实现Runnable接口的好处:
 * 1.将线程的任务从线程的子类中分离出来,进行了单独的封装[脱离了Thread体系]
 *   按照面向对象的思想将任务封装成对象
 * 2.避免了java单继承的局限性
 * 
 * 所以,创建线程的第二种方式较为常用.
 * @author 罗摩衔那
 *
 */
public class Implement_Detai {

}

class Thread
{
    private Runnable r;
    Thread(){//第一种方法的行走路线
        
    }
    Thread(Runnable r){//第二种方法的行走路线
        this.r=r;
    }
    
    public void run() {
        r.run();
    }
    
    public void start() {
        run();//启动线程
    }
}

   所以说,Ticket_Demo程序中,Thread b=new Thread(train);中的train其实就是传进了一个Ticket对象作参数,开始我也有疑问不是传Runnable接口的对象进去嘛,怎么是其子类对象,这个我是这么理解的:其实我们java中的继承父类子类的关系就是更高级的抽象罢了,举个栗子:person是父类,人会说话,会呼吸(能力),student类继承了person类,student类会学习(能力),难道学生就不会呼吸,说话了嘛?这个传入其子类对象,也是合理的.传入后也就相当于获取到其子类的run方法了(结合第二段代码理解).

   创建了几个thread对象不就像几个人在卖票,传入的是同一个train对象不就是执行的是同一个run方法(虽然开启了结果run方法,其实本质上是一个),这时候我们想卖不同的票,那就再创建一个Ticket对象.


 

 最后看看继承thread方法的卖票程序

class Ticket extends thread{
    private int num=100;//售票数一百张
    
    public void run() 
    {
             while(true)
           {
              if(num>0)
              {
                   System.out.println(Thread.currentThread().getName()+"...."+num--);
               }
           }
        
    }
}
public class Ticket_Demo {
    public static void main(String[] args) {
      Ticket c=new Ticket();
      Ticket d=new Ticket();

      c.stat();
      d.stat();
        
    }
}

   就在与mian程序里的区别了,因为Ticket继承了Thread,所以就拥有了父类的start()开启线程的能力,不需要创建Thread对象[在体制内],可以这时候开启线程确是不同的run方法,也就是不同的num对象,你开启了几个线程,就创建了多少个一百张票惹~

posted @ 2018-10-24 21:32  静心*尽力  阅读(227)  评论(0编辑  收藏  举报