精华内容
下载资源
问答
  • 那么这两种实现多线程的方式在应用上有什么区别呢? http://yuelangyc.iteye.com/blog/1056393 为了回答这个问题,我们可以通过编写一段代码来进行分析。我们用代码来模拟铁路售票系统,实现通过四个售票点发售某日...

    java中有两种实现多线程的方式。一是直接继承Thread类,二是实现Runnable接口。那么这两种实现多线程的方式在应用上有什么区别呢?

    http://yuelangyc.iteye.com/blog/1056393

    为了回答这个问题,我们可以通过编写一段代码来进行分析。我们用代码来模拟铁路售票系统,实现通过四个售票点发售某日某次列车的100张车票,一个售票点用一个线程表示。

    我们首先这样编写这个程序:

    class ThreadTest extends Thread{
     2      private int ticket = 100;
     3      public void run(){
     4        while(true){
     5          if(ticket > 0){
     6             System.out.println(Thread.currentThread().getName() +
     7               "is saling ticket" + ticket--);
     8          }else{
     9            break;
    10          }
    11       }
    12    }
    13 }

    main测试类:

    public class ThreadDome1{
    2   public static void main(String[] args){
    3     ThreadTest t = new ThreadTest();
    4       t.start();
    5       t.start();
    6       t.start();
    7       t.start();
    8    }
    9 }

    上面的代码中,我们用ThreadTest类模拟售票处的售票过程,run方法中的每一次循环都将总票数减1,模拟卖出一张车票,同时该车票号打 印出来,直接剩余的票数到零为止。在ThreadDemo1类的main方法中,我们创建了一个线程对象,并重复启动四次,希望通过这种方式产生四个线 程。从运行的结果来看我们发现其实只有一个线程在运行,这个结果告诉我们:一个线程对象只能启动一个线程,无论你调用多少遍start()方法,结果只有 一个线程。

    我们接着修改ThreadDemo1,在main方法中创建四个Thread对象:

    class ThreadTest extends Thread{
     2   private int ticket = 100;
     3   public void run(){
     4       while(true){
     5       if(ticket > 0){
     6       System.out.println(Thread.currentThread().getName() +
     7           " is saling ticket" + ticket--);
     8       }else{
     9          break;
    10       }
    11     }
    12   }
    13 }

    public class ThreadDemo1{
    2   public static void main(String[] args){
    3     new ThreadTest().start();
    4     new ThreadTest().start();
    5     new ThreadTest().start();
    6     new ThreadTest().start();
    7  }
    8 }

    这下达到目的了吗?

    从结果上看每个票号都被打印了四次,即四个线程各自卖各自的100张票,而不去卖共同的100张票。这种情况是怎么造成的呢?我们需要的是,多个线程去处 理同一个资源,一个资源只能对应一个对象,在上面的程序中,我们创建了四个ThreadTest对象,就等于创建了四个资源,每个资源都有100张票,每 个线程都在独自处理各自的资源。

    经过这些实验和分析,可以总结出,要实现这个铁路售票程序,我们只能创建一个资源对象,但要创建多个线程去处理同一个资源对象,并且每个线程上所运行的是相同的程序代码。在回顾一下使用接口编写多线程的过程。

    class ThreadTest implements Runnable{
      private int tickets = 100;
      public void run(){
         while(true){
         if(tickets > 0){
           System.out.println(Thread.currentThread().getName() +
              " is saling ticket " + tickets--);
          }
        }
      }
    }
    

    public class ThreadDemo1{
       public static void main(String[] args){
        ThreadTest t = new ThreadTest();
          new Thread(t).start();
          new Thread(t).start();
          new Thread(t).start();
          new Thread(t).start();
       }
     }


    上面的程序中,创建了四个线程,每个线程调用的是同一个ThreadTest对象中的run()方法,访问的是同一个对象中的变量 (tickets)的实例,这个程序满足了我们的需求。在Windows上可以启动多个记事本程序一样,也就是多个进程使用同一个记事本程序代码。
    可见,实现Runnable接口相对于继承Thread类来说,有如下显著的好处:
    (1)适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码,数据有效的分离,较好地体现了面向对象的设计思想。
    (2)可以避免由于Java的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了。
    (3)有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。 
    多个线程操作相同的数据,与它们的代码无关。当共享访问相同的对象是,即它们共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例。

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    展开全文
  • 主要为大家区分了java创建线程的两种方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 创建线程的两种方法

    2017-07-17 23:16:00
    创建线程的两种方法:  1、继承Thread类,并重写Thread类的run方法  2、实现接口Runnable的run方法。  注意:另外还有一种创建线程的方法笔者没有指出,使用线程池方式—Callable接口。Callable接口实现类,call...

    创建线程的两种方法:

      1、继承Thread类,并重写Thread类的run方法

      2、实现接口Runnable的run方法。

      注意:另外还有一种创建线程的方法笔者没有指出,使用线程池方式—Callable接口。Callable接口实现类,call方法可抛出异常、返回线程任务执行完毕后的结果

      面试问题:Thread类直接调用run()和调用start()方法的区别是什么呢?

        答:Thread的start()方法才能创建一个新的线程。如果直接调用run()方法,相当于直接调用一个类中的方法,不会创建一个新的线程。

    1.5 创建线程方式一继承Thread类
    创建线程的步骤:
    1 定义一个类继承Thread。
    2 重写run方法。
    3 创建子类对象,就是创建线程对象。
    4 调用start方法,开启线程并让线程执行,同时还会告诉jvm去调用run方法。
     测试类

     1 public class Demo01 {
     2     public static void main(String[] args) {
     3         //创建自定义线程对象
     4         MyThread mt = new MyThread("新的线程!");
     5         //开启新线程
     6         mt.start();
     7         //在主方法中执行for循环
     8         for (int i = 0; i < 10; i++) {
     9             System.out.println("main线程!"+i);
    10         }
    11     }
    12 }

     自定义线程类

    public class MyThread extends Thread {
        //定义指定线程名称的构造方法
        public MyThread(String name) {
            //调用父类的String参数的构造方法,指定线程的名称
            super(name);
        }
        /**
         * 重写run方法,完成该线程执行的逻辑
         */
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(getName()+":正在执行!"+i);
            }
        }
    }

    思考:线程对象调用 run方法和调用start方法区别?
    线程对象调用run方法不开启线程。仅是对象调用方法。线程对象调用start开启线程,并让jvm调用run方法在开启的线程中执行。
    1.5.1 继承Thread类原理
    我们为什么要继承Thread类,并调用其的start方法才能开启线程呢?
    继承Thread类:因为Thread类用来描述线程,具备线程应该有功能。那为什么不直接创建Thread类的对象呢?如下代码:
    Thread t1 = new Thread();
    t1.start();//这样做没有错,但是该start调用的是Thread类中的run方法,而这个run方法没有做什么事情,更重要的是这个run方法中并没有定义我们需要让线程执行的代码。

    创建线程的目的是什么?
    是为了建立程序单独的执行路径,让多部分代码实现同时执行。也就是说线程创建并执行需要给定线程要执行的任务。
    对于之前所讲的主线程,它的任务定义在main函数中。自定义线程需要执行的任务都定义在run方法中。
    Thread类run方法中的任务并不是我们所需要的,只有重写这个run方法。既然Thread类已经定义了线程任务的编写位置(run方法),那么只要在编写位置(run方法)中定义任务代码即可。所以进行了重写run方法动作。
    1.5.2 多线程的内存图解
    多线程执行时,到底在内存中是如何运行的呢?
    以上个程序为例,进行图解说明:
    多线程执行时,在栈内存中,其实每一个执行线程都有一片自己所属的栈内存空间。进行方法的压栈和弹栈。

    当执行线程的任务结束了,线程自动在栈内存中释放了。但是当所有的执行线程都结束了,那么进程就结束了。
    1.5.3 获取线程名称
    开启的线程都会有自己的独立运行栈内存,那么这些运行的线程的名字是什么呢?该如何获取呢?既然是线程的名字,按照面向对象的特点,是哪个对象的属性和谁的功能,那么我们就去找那个对象就可以了。查阅Thread类的API文档发现有个方法是获取当前正在运行的线程对象。还有个方法是获取当前线程对象的名称。既然找到了,我们就可以试试。

     Thread.currentThread()获取当前线程对象
     Thread.currentThread().getName();获取当前线程对象的名称

     1 class MyThread extends Thread {  //继承Thread
     2     MyThread(String name){
     3         super(name);
     4     }
     5     //复写其中的run方法
     6     public void run(){
     7         for (int i=1;i<=20 ;i++ ){
     8             System.out.println(Thread.currentThread().getName()+",i="+i);
     9         }
    10     }
    11 }
    12 class ThreadDemo {
    13     public static void main(String[] args)     {
    14         //创建两个线程任务
    15         MyThread d = new MyThread();
    16         MyThread d2 = new MyThread();
    17         d.run();//没有开启新线程, 在主线程调用run方法
    18         d2.start();//开启一个新线程,新线程调用run方法
    19     }
    20 }

    通过结果观察,原来主线程的名称:main;自定义的线程:Thread-0,线程多个时,数字顺延。如Thread-1......
    进行多线程编程时,不要忘记了Java程序运行是从主线程开始,main方法就是主线程的线程执行内容。
    1.6 创建线程方式—实现Runnable接口
    创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后创建Runnable的子类对象,传入到某个线程的构造方法中,开启线程。
    为何要实现Runnable接口,Runable是啥玩意呢?继续API搜索。
    查看Runnable接口说明文档:Runnable接口用来指定每个线程要执行的任务。包含了一个 run 的无参数抽象方法,需要由接口实现类重写该方法。

     接口中的方法

     Thread类构造方法

    创建线程的步骤。
    1、定义类实现Runnable接口。
    2、覆盖接口中的run方法。。
    3、创建Thread类的对象
    4、将Runnable接口的子类对象作为参数传递给Thread类的构造函数。
    5、调用Thread类的start方法开启线程。
     代码演示:

     1 public class Demo02 {
     2     public static void main(String[] args) {
     3         //创建线程执行目标类对象
     4         Runnable runn = new MyRunnable();
     5         //将Runnable接口的子类对象作为参数传递给Thread类的构造函数
     6         Thread thread = new Thread(runn);
     7         Thread thread2 = new Thread(runn);
     8         //开启线程
     9         thread.start();
    10         thread2.start();
    11         for (int i = 0; i < 10; i++) {
    12             System.out.println("main线程:正在执行!"+i);
    13         }
    14     }
    15 }

     自定义线程执行任务类

     1 public class MyRunnable implements Runnable{
     2 
     3     //定义线程要执行的run方法逻辑
     4     @Override
     5     public void run() {
     6         
     7         for (int i = 0; i < 10; i++) {
     8             System.out.println("我的线程:正在执行!"+i);
     9         }
    10     }
    11 }

     

    1.6.1 实现Runnable的原理
    为什么需要定一个类去实现Runnable接口呢?继承Thread类和实现Runnable接口有啥区别呢?
    实现Runnable接口,避免了继承Thread类的单继承局限性。覆盖Runnable接口中的run方法,将线程任务代码定义到run方法中。
    创建Thread类的对象,只有创建Thread类的对象才可以创建线程。线程任务已被封装到Runnable接口的run方法中,而这个run方法所属于Runnable接口的子类对象,所以将这个子类对象作为参数传递给Thread的构造函数,这样,线程对象创建时就可以明确要运行的线程的任务。
    1.6.2 实现Runnable的好处
    第二种方式实现Runnable接口避免了单继承的局限性,所以较为常用。实现Runnable接口的方式,更加的符合面向对象,线程分为两部分,一部分线程对象,一部分线程任务。继承Thread类,线程对象和线程任务耦合在一起。一旦创建Thread类的子类对象,既是线程对象,有又有线程任务。实现runnable接口,将线程任务单独分离出来封装成对象,类型就是Runnable接口类型。Runnable接口对线程对象和线程任务进行解耦。

    转载于:https://www.cnblogs.com/Ycheng/p/7197742.html

    展开全文
  • 创建线程的两种方法,及之间的区别

    千次阅读 2013-08-04 23:33:09
    创建线程的第一:继承Thread类. 步骤: 1,定义类继承Thread. 2,复写Thread类中的run方法. 目的:将自定义代码存储在run方法.让线程运行. 3,创建线程的子类对象. 4,调用线程的start方法,   该方法两个作用:...

    创建线程的第一种:继承Thread类.

    步骤:

    1,定义类继承Thread.

    2,复写Thread类中的run方法.

    目的:将自定义代码存储在run方法.让线程运行.

    3,创建线程的子类对象.

    4,调用线程的start方法,

       该方法两个作用:启动线程,调用run方法.


    创建线程的第二种方式:实现Runnable接口

    步骤:

    1,定义类实现Runnable接口

    2,覆盖Runnable接口中的run方法.

      将线程要运行的代码存放在该run方法中.

    3,通过Thread类建立线程的对象.

    4,Runnable接口的子类对象作为实际参数传递给Thread类的构造函数.

       为什么要将Runnable接口的子类对象传递给Thread的构造函数.

       因为,自定义的run方法所属的对象是Runnable接口的子类对象.

       所以要让线程去执行指定对象的run方法.就必须明确该run方法所属对象.

    5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法.

    实现方式和继承方式的区别

    1,继承方式的代码比较简单.( 在没有父类时,使用继承方式.)

    实现方式好处:避免了单继承的局限性.

    在定义线程时,建议使用实现方式.

     

    2,存放代码位置不一样

    继承Thread:线程代码存放Thread子类的run方法中.

    实现Runnable,线程代码存在接口的子类的run方法中.


    展开全文
  • java中线程的创建可以有两种方法:1、继承Thread类 2、实现Runnable接口两者区别:1、继承Thread类创建线程的方法,在继承了Thread类之后,不能再继承其他的方法,(在java中支持单继承),这样灵活性就不如实现...

     java中线程的创建可以有两种方法:1、继承Thread类 2、实现Runnable接口

    两者区别:

    1、继承Thread类创建线程的方法,在继承了Thread类之后,不能再继承其他的方法,(在java中支持单继承),这样灵活性就不如实现Runnable接口来创建线程的方法了;

    2、使用实现Runnable接口来创建线程可以达到资源共享!(继承Thread类创建线程也可以实现资源共享,但是比较的麻烦。)

    在我们创建线程的时候都会优先采用实现Runnable接口的方法。

     

    我们首先用第一种方式写一个线程类:
    代码如下:
    package Ticket;

    public class Extends {
     
     public static void main(String[] args){
              //实例化进程并准备执行
              new Thread(new MyThread(),"001窗口").start();
              new Thread(new MyThread(),"001窗口").start();
              new Thread(new MyThread(),"001窗口").start();
      
             }

    }

    class MyThread extends Thread{
             //定义一个变量
              private int ticket = 10;
     
              public void run(){
          
              //这里之所以要循环300次,就是为了让所有的 车票都卖出去!可能你会想,为什么不是30呢?
              //嘿嘿。。。聪明的你肯定明白这个循环的次数为什么会多出票数很多?=====其实我开始也不知道!!!  ==|||  
             
              for(int i=0;i<300;i++){
                   try {
                        //调用sell()方法
                        this.sell();
                        Thread.sleep(10);
                     } catch (InterruptedException e) {
                                e.printStackTrace();
                     }
      }
      
     }
               public void sell(){
                      if(ticket>0){
                               System.out.println(Thread.currentThread().getName() + " ===> 还剩下" + (ticket--) + "车票");
                      }
     }
    }

    看看这个程序的运行结果你就明白为什么继承Thread类实现线程类的一个弊端  


    我们来分析一下代码,查看main函数:
              new Thread(new MyThread(),"001窗口").start();
              new Thread(new MyThread(),"001窗口").start();
              new Thread(new MyThread(),"001窗口").start();

    我们可以看出,实例化了三个MyThread类,这样的话,private int ticket = 10;就运行了三次,所以ticket打印出来的 也就是30张;在这里注意一下并不是ticket赋值为30,而是ticket赋值为10,但赋值了三次!!!也就是现在有三个ticket!!!
    这样并不能实现资源共享!
    我们知道我们利用多线程就是为了将多个线程去处理一个数据的集合!!! 他们是同时处理的!!!如果向上面的话,并没有将数据的集合(ticket)进行共享,而是将每一个类都从新建了一个数据的集合,分别对自己的集合进行处理!!!!
    如果想解决这个问题,其实也很简单,不过如果当数据的类型和种类比较多的时候,这样写就太麻烦了!!!!

    那实现Runnable接口的线程类可不可以呢!!???

    下面来看一看:

    代码如下:

    package IO;

    public class Inter {

        public static void main(String[] args){
            //声明并实例化一个MyThread01类
            MyThread01 mt = new MyThread01();
            new Thread(mt,"001窗口").start();
            new Thread(mt,"002窗口").start();
            new Thread(mt,"003窗口").start();

        }
        
    }

    class MyThread01 implements Runnable{
        
        private int ticket = 10;    
        public void run(){    
            for(int i=0;i<200;i++){
                try {
                    this.sell();
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
        }
        public void sell(){
            if(ticket>0){
                System.out.println(Thread.currentThread().getName() + " ===> 还剩下" + (ticket--) + "车票");
            }
            
        }  
    }


    看看这个结果是不是和自己想的一样啊!!!这样就可以了!!!用这个方法去创建一个线程类是不是可以达到资源共享啊!!!
    其实啊!我看来,所谓的资源共享也就是将一个数据的集合让多个线程去处理!!!
    我们看一下代码!!!
            MyThread01 mt = new MyThread01();
            new Thread(mt,"001窗口").start();
            new Thread(mt,"002窗口").start();
            new Thread(mt,"003窗口").start();

    我们可以看出这个过程中,我们只声明并实例化了一个MyThread01类,也就是说在这里过程中,给ticket进行了初始化!!!
    但大家要注意的是:真正创建处理数据的线程是
            new Thread(mt,"001窗口").start();
            new Thread(mt,"002窗口").start();
            new Thread(mt,"003窗口").start();
    因此,这样可以将一个ticket的数据集 由三个线程来处理!!!
    这样就是所谓的资源共享!!!

    展开全文
  • 1.线程的概念 以往我们初级编程大多都是单线程的,即每次只有一条执行路径,但现实生活中很多过程都是可以多个途径一起执行的,并且现在的计算机都是支持多线程的,所以学会使用多进程能更好地提高计算机的运行效率...
  • Qt创建线程的两种方法

    万次阅读 多人点赞 2017-12-25 15:33:54
    1.摘要 Qt有两种多线程的方法,其中一种是继承QThread的run函数,另外一种是把一个继承于QObject的类转移到一个Thread里。 Qt4.8之前都是使用继承QThread的run这种方法,但是Qt4.8之后,Qt官方...两种方法区别不大...
  • 创建线程的两种方式区别

    千次阅读 2019-02-24 12:54:54
    Java提供了线程类Thread来创建多...要产生一个线程,有两种方法: ◆需要从Java.lang.Thread类派生一个新的线程类,重载它run()方法。  ◆实现Runnalbe接口,重载Runnalbe接口中run()方法。 下面就从几个例...
  • C++利用API接口createthread创建线程和利用库thread创建线程有什么具体的区别,希望具体点(什么时候用哪)。
  • 1.创建线程的两种方式及区别 采用继承Thread类方式: (1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。 (2)缺点:因为线程类已经继承了Thread...
  • 摘要:其实两种方法归结起来看还是一种,都是利用Thread构造器进行创建区别就是一种是无参,一种是有参。一、继承Thread线程类:通过继承Thread类,重写run方法,子类对象就可以调用start方法启动线程,JVM...
  •  为什么Java要提供两种方法创建线程呢?它们都有哪些区别?相比而言,哪一种方法更好呢?  在Java中,类仅支持单继承,也是说,当定义一个新时候,它只能扩展一个外部类.这样,如果创建自定义线程
  • 1、我用run()启动线程,不用start()行不行? 2、创建线程的两种方式中,都调用start()方法了,但有什么区别呢?
  • 进程和线程的区别 1. 一个进程至少有一个线程 2. 进程是作为资源分配的单位,而线程是调度和执行的单位。 3. 进程关闭了线程一定关闭,线程关闭了进程不一定关闭。 4. 线程有几状态:创建状态(new)、就绪状态...
  • 第一种方法:继承Thread类 public class NewThread extends Thread { public void run() { for(int i=0;i&amp;amp;lt;20;i++) { System.out.println(i); } } } public class Test { public static...
  • 创建线程的两种方式以及区别

    千次阅读 2017-09-24 22:35:41
     (1)代码简单,直接通过Thread构造方法创建线程,且访问当前线程时,直接调用this.即可获得当前线程。  (2)因为已经继承Thread类,所以不能继承其他父类。  (3)若要个线程之间共享变量时,需要在声明...
  • 创建线程的种方法

    2018-02-27 21:32:34
    java中创建线程的种方法以及区别Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。Java可以用三种方式来创建线程,如下所示:1)继承Thread类创建线程2)实现Runnable接口创建线程3)...
  • 前言:看到很多博客上都写过多线程的实例以及这两种方式的区别,其中让我报有疑惑的一点是很多都说继承Thread而实现的多线程无法共享资源?我自己下来敲了敲,再结合一些资料做了如下总结 先创建了两个类,一个是...
  • 主要介绍通过继承Thread类的方法创建线程的步骤和实现Runnable接口的方法创建线程的步骤。比较了Thread和Runnable两者的区别、联系、共同点,解释为什么开发中应该用Runnable来创建多线程。
  • 两种方式的区别: 继承Thread:线程代码存放Thread子类run方法中 实现Runable接口线程代码在接口子类的run方法线程的运行出现安全问题 问题的原因: 当多条语句在操作同一个线程共享数据时 一个线程对多条...
  • 创建线程两种方法: 需要从Java.lang.Thread类派生一个新线程类,重载它run()方法; 实现Runnalbe接口,重载Runnalbe接口中run()方法。 一、将类声明为Thread子类。该子类应重写Thread 类 run 方法...
  • 1、多线程安全问题分析2、多线程安全问题解决3、多线程安全问题细节 ... 3.1、同步好处和弊端 3.2、... 4.1、同步是否可以加在run方法上 4.2、同步方法锁 5、单例懒汉式线程并发问题6、死锁示例7、生

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 648
精华内容 259
关键字:

创建线程的两种方法的区别