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


    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对象,你开启了几个线程,就创建了多少个一百张票惹~

  • 相关阅读:
    react路由组件&&非路由组件
    react函数式组件(非路由组件)实现路由跳转
    react使用antd组件递归实现左侧菜单导航树
    【LeetCode】65. Valid Number
    【LeetCode】66. Plus One (2 solutions)
    【LeetCode】68. Text Justification
    【LeetCode】69. Sqrt(x) (2 solutions)
    【LeetCode】72. Edit Distance
    【LeetCode】73. Set Matrix Zeroes (2 solutions)
    【LeetCode】76. Minimum Window Substring
  • 原文地址:https://www.cnblogs.com/zjm1999/p/9846303.html
Copyright © 2020-2023  润新知