zoukankan      html  css  js  c++  java
  • 多线程的卖票示例来理解两种创建线程方法的区别

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

  • 相关阅读:
    SQL SERVER 博客
    deadlock
    dbcc 官方文档
    HOW TO CHECK FOR ACTIVE TRACE FLAGS ON MICROSOFT SQL SERVER
    Enable a SQL Server Trace Flag Globally on Linux
    SQL server 2008 安装问题解决 转
    Looking deeper into SQL Server using Minidumps
    sql-server-linux 官网
    破解SQLServer for Linux预览版的3.5GB内存限制 (RHEL篇) 转
    SQL Server on Linux: How? Introduction: SQL Server Blog
  • 原文地址:https://www.cnblogs.com/zjm1999/p/9846303.html
Copyright © 2011-2022 走看看