`
mars914
  • 浏览: 429712 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java中继承thread类与实现Runnable接口的区别

    博客分类:
  • java
阅读更多

Java中线程的创建有两种方式:

 

1.  通过继承Thread类,重写Threadrun()方法,将线程运行的逻辑放在其中

2.  通过实现Runnable接口,实例化Thread

 

    在实际应用中,我们经常用到多线程,如车站的售票系统,车站的各个售票口相当于各个线程。当我们做这个系统的时候可能会想到两种方式来实现,继承Thread类或实现Runnable接口,现在看一下这两种方式实现的两种结果。


package com.threadtest;
class MyThread extends Thread{
    
    private int ticket = 10;
    private String name;
    public MyThread(String name){
        this.name =name;
    }
    
    public void run(){
        for(int i =0;i<500;i++){
            if(this.ticket>0){
                System.out.println(this.name+"卖票---->"+(this.ticket--));
            }
        }
    }
}
public class ThreadDemo {

    
    public static void main(String[] args) {
        MyThread mt1= new MyThread("一号窗口");
        MyThread mt2= new MyThread("二号窗口");
        MyThread mt3= new MyThread("三号窗口");
        mt1.start();
        mt2.start();
        mt3.start();
    }

}

 

运行结果如下:

一号窗口卖票---->10
一号窗口卖票---->9
二号窗口卖票---->10
一号窗口卖票---->8
一号窗口卖票---->7
一号窗口卖票---->6
三号窗口卖票---->10
一号窗口卖票---->5
一号窗口卖票---->4
一号窗口卖票---->3
一号窗口卖票---->2
一号窗口卖票---->1
二号窗口卖票---->9
二号窗口卖票---->8
三号窗口卖票---->9
三号窗口卖票---->8
三号窗口卖票---->7
三号窗口卖票---->6
三号窗口卖票---->5
三号窗口卖票---->4
三号窗口卖票---->3
三号窗口卖票---->2
三号窗口卖票---->1
二号窗口卖票---->7
二号窗口卖票---->6
二号窗口卖票---->5
二号窗口卖票---->4
二号窗口卖票---->3
二号窗口卖票---->2
二号窗口卖票---->1

 

通过实现Runnable接口的代码如下:
 

package com.threadtest;
class MyThread1 implements Runnable{
    private int ticket =10;
    private String name;
    public void run(){
        for(int i =0;i<500;i++){
            if(this.ticket>0){
                System.out.println(Thread.currentThread().getName()+"卖票---->"+(this.ticket--));
            }
        }
    }
}
public class RunnableDemo {

    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //设计三个线程
         MyThread1 mt = new MyThread1();
         Thread t1 = new Thread(mt,"一号窗口");
         Thread t2 = new Thread(mt,"二号窗口");
         Thread t3 = new Thread(mt,"三号窗口");
//         MyThread1 mt2 = new MyThread1();
//         MyThread1 mt3 = new MyThread1();
         t1.start();
         t2.start();
         t3.start();
    }

}

 

运行结果如下:

一号窗口卖票---->10
三号窗口卖票---->9
三号窗口卖票---->7
三号窗口卖票---->5
三号窗口卖票---->4
三号窗口卖票---->3
三号窗口卖票---->2
三号窗口卖票---->1
一号窗口卖票---->8
二号窗口卖票---->6

 

 

    为什么会出现这种结果呐。我们不妨做个比喻,其实刚的程序,

继承Thread类的,我们相当于拿出三件事即三个卖票10张的任务分别分给三个窗口,他们各做各的事各卖各的票各完成各的任务,因为MyThread继承Thread类,所以在new MyThread的时候在创建三个对象的同时创建了三个线程;

实现Runnable的, 相当于是拿出一个卖票10张得任务给三个人去共同完成,new MyThread相当于创建一个任务,然后实例化三个Thread,创建三个线程即安排三个窗口去执行。

     

用图表示如下:



 

   在我们刚接触的时候可能会迷糊继承Thread类和实现Runnable接口实现多线程,其实在接触后我们会发现这完全是两个不同的实现多线程,一个是多个线程分别完成自己的任务,一个是多个线程共同完成一个任务

     

    其实在实现一个任务用多个线程来做也可以用继承Thread类来实现只是比较麻烦,一般我们用实现Runnable接口来实现,简洁明了。

      

    大多数情况下,如果只想重写 run() 方法,而不重写其他 Thread 方法,那么应使用 Runnable 接口。这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应为该类(Thread)创建子类。

 

 

 

 

  • 大小: 44 KB
  • 大小: 28.3 KB
分享到:
评论
17 楼 jamin415 2017-02-08  
感觉楼主还没理解透彻,可以先看看源代码这两个类是怎么实现的,Thread是实现了Runable的接口,知道这个就明了了
16 楼 hudazheng 2017-01-04  
mars914 写道
a455642158 写道
非常感谢……对于下面这段代码:
         MyThread1 mt = new MyThread1(); 
         Thread t1 = new Thread(mt,"一号窗口"); 
         Thread t2 = new Thread(mt,"二号窗口"); 
         Thread t3 = new Thread(mt,"三号窗口");
我们老大非常反感,说你这样写是错的,跟我说是在api里面找不到根据。
我也不会解释,哎,无语。

jdk api 里面没有说明,但是可以通过程序的执行来说明,事实。

MyThread1 mt = new MyThread1(); 改成 Runnable mt = new MyThread1();
15 楼 coolcgp 2016-11-16  
博主用继承Thread用new,用Runnable时用共享,概念搞错了,Thread也能共享资源。不过,加油,大家都是这么走过来的。只是希望后来者提醒,仅此而已。
14 楼 Koby丶 2016-07-20  
flight2006 写道
这篇文章举例和结论都没错,但是博主理解有误!
实现Runable的一个好处就是能实现资源共享,结论正确(因为继承Thread实现不了)
但是不是说实现Runable就是实现了资源共享,实际上还是通过
MyThread1 mt = new MyThread1();  

这个对象实现的共享,如果是三个不同对象:
MyThread1 mt1 = new MyThread1(); 
MyThread1 mt2 = new MyThread1(); 
MyThread1 mt2 = new MyThread1(); 
Thread t1 = new Thread(mt1,"一号窗口");  
Thread t2 = new Thread(mt2,"二号窗口");  
Thread t3 = new Thread(mt3,"三号窗口");  


这样执行的结果是和上面完全一样的。

总结一下,实现Runable除了避免单继承的局限外,还有个好处就是能实现不同进程资源共享,而继承Thread没有这个功能。并不是这个特点是两者的绝对区别,继承Runable你可以选择不共享。


Thread也能共享资源,
MyThread mt= new MyThread(); 
Thread t1 = new Thread(mt,"一号窗口");   
Thread t2 = new Thread(mt,"二号窗口");  
Thread t3 = new Thread(mt,"三号窗口");
执行结果和Runnable一样
13 楼 drivedreams 2016-04-07  
MyThread1 mt = new MyThread1(); 
Thread t1 = new Thread(mt,"一号窗口"); 
Thread t2 = new Thread(mt,"二号窗口"); 
Thread t3 = new Thread(mt,"三号窗口");
你这种写法存在很大的问题,t1读取ticket=1,因为是多线程t2也可能在读取ticket=1,
t1对ticket-- ,ticket =0 ,此时t2也对ticket--,因为判断还有票,那么此时的ticket=-1
12 楼 flight2006 2015-08-28  
这篇文章举例和结论都没错,但是博主理解有误!
实现Runable的一个好处就是能实现资源共享,结论正确(因为继承Thread实现不了)
但是不是说实现Runable就是实现了资源共享,实际上还是通过
MyThread1 mt = new MyThread1();  

这个对象实现的共享,如果是三个不同对象:
MyThread1 mt1 = new MyThread1(); 
MyThread1 mt2 = new MyThread1(); 
MyThread1 mt2 = new MyThread1(); 
Thread t1 = new Thread(mt1,"一号窗口");  
Thread t2 = new Thread(mt2,"二号窗口");  
Thread t3 = new Thread(mt3,"三号窗口");  


这样执行的结果是和上面完全一样的。

总结一下,实现Runable除了避免单继承的局限外,还有个好处就是能实现不同进程资源共享,而继承Thread没有这个功能。并不是这个特点是两者的绝对区别,继承Runable你可以选择不共享。
11 楼 best_programmer 2014-10-07  
在世界的中心呼喚愛 写道
这个文章有错。。

MyThread1 mt = new MyThread1();  
         Thread t1 = new Thread(mt,"一号窗口");  
         Thread t2 = new Thread(mt,"二号窗口");  
         Thread t3 = new Thread(mt,"三号窗口");  


这里代码有问题啊,不是Thread和runnable的问题。。这里共享一个资源了。。
其实就是接口和继承的问题。。

 
         Thread t1 = new Thread(new MyThread1(),"一号窗口");  
         Thread t2 = new Thread(new MyThread1(),"二号窗口");  
         Thread t3 = new Thread(new MyThread1(),"三号窗口");  


这样才是ok的。每一个线程一个资源

thanks,明白了。楼主自己把自己讲糊涂了,让我也糊涂了。他的结果出现的原因是因为资源共享,与线程的实现方式并无关······大牛,接着帮忙回答下这个问题呗http://bbs.csdn.net/topics/390889930
10 楼 在世界的中心呼喚愛 2014-09-01  
这个文章有错。。

MyThread1 mt = new MyThread1();  
         Thread t1 = new Thread(mt,"一号窗口");  
         Thread t2 = new Thread(mt,"二号窗口");  
         Thread t3 = new Thread(mt,"三号窗口");  


这里代码有问题啊,不是Thread和runnable的问题。。这里共享一个资源了。。
其实就是接口和继承的问题。。

 
         Thread t1 = new Thread(new MyThread1(),"一号窗口");  
         Thread t2 = new Thread(new MyThread1(),"二号窗口");  
         Thread t3 = new Thread(new MyThread1(),"三号窗口");  


这样才是ok的。每一个线程一个资源
9 楼 luo877280 2014-08-19  
我想说这个 没解决接口和继承的问题   楼主 你看着改了吧!!!
8 楼 learnTECh 2014-07-10  
当extends Thread时,
MyThread mt1= new MyThread("一号窗口"); 
MyThread mt2= new MyThread("二号窗口"); 
MyThread mt3= new MyThread("三号窗口");
创建了3个MyThread对象,分别执行start()方法,每个对象都有自己的ticket=10
如果private static ticket = 10; 就可以实现拥有共同的ticket=10
执行结果就跟实现Runnable一样了


当实现Runnable的时候
MyThread1 mt = new MyThread1(); 
Thread t1 = new Thread(mt,"一号窗口"); 
Thread t2 = new Thread(mt,"二号窗口"); 
Thread t3 = new Thread(mt,"三号窗口");
创建了一个对象,3个进程, 共用一个对象,共同拥有一个ticket=10

这样理解对不对?
7 楼 best_programmer 2014-05-09  
eighteencold 写道
汗,你还是把这篇删了吧,太误人子弟了,这明明是
MyThread1 mt = new MyThread1(); 
Thread t1 = new Thread(mt,"一号窗口"); 
Thread t2 = new Thread(mt,"二号窗口"); 
Thread t3 = new Thread(mt,"三号窗口");

MyThread mt1= new MyThread("一号窗口"); 
MyThread mt2= new MyThread("二号窗口"); 
MyThread mt3= new MyThread("三号窗口"); 
mt1.start(); 
mt2.start(); 
mt3.start(); 
两种写法之间的区别,不要上升到Java中继承thread类与实现Runnable接口的区别好不!

问下这两种写法不是正好对应继承thread类与实现Runnable接口吗?哪儿错了吗?只不过实现Runnable接口平常都是创建匿名对象直接调用start()方法吧
6 楼 eighteencold 2013-11-29  
汗,你还是把这篇删了吧,太误人子弟了,这明明是
MyThread1 mt = new MyThread1(); 
Thread t1 = new Thread(mt,"一号窗口"); 
Thread t2 = new Thread(mt,"二号窗口"); 
Thread t3 = new Thread(mt,"三号窗口");

MyThread mt1= new MyThread("一号窗口"); 
MyThread mt2= new MyThread("二号窗口"); 
MyThread mt3= new MyThread("三号窗口"); 
mt1.start(); 
mt2.start(); 
mt3.start(); 
两种写法之间的区别,不要上升到Java中继承thread类与实现Runnable接口的区别好不!
5 楼 ByteCoder 2013-04-28  
对于第一种写法
引用
MyThread mt1= new MyThread("一号窗口"); 
        MyThread mt2= new MyThread("二号窗口"); 
        MyThread mt3= new MyThread("三号窗口");

由于Thread类本身也实现了Runnable接口,所以上面的写法也可以写成
 MyThread mt= new MyThread();
 Thread t1 = new Thread(mt,"一号窗口");  
 Thread t2 = new Thread(mt,"二号窗口"); 
 Thread t3 = new Thread(mt,"三号窗口"); 

当然这种写法并不好,但足以说明你的想法是错误
对于第二种写法
引用

MyThread1 mt = new MyThread1(); 
Thread t1 = new Thread(mt,"一号窗口"); 
Thread t2 = new Thread(mt,"二号窗口"); 
Thread t3 = new Thread(mt,"三号窗口");

可以改成
引用

Thread t1 = new Thread(new MyThread1(),"一号窗口"); 
Thread t2 = new Thread(new MyThread1(),"二号窗口"); 
Thread t3 = new Thread(new MyThread1(),"三号窗口");

这两种的区别主要还是接口和继承类的区别
4 楼 a455642158 2012-07-20  
mars914 写道
a455642158 写道
非常感谢……对于下面这段代码:
         MyThread1 mt = new MyThread1(); 
         Thread t1 = new Thread(mt,"一号窗口"); 
         Thread t2 = new Thread(mt,"二号窗口"); 
         Thread t3 = new Thread(mt,"三号窗口");
我们老大非常反感,说你这样写是错的,跟我说是在api里面找不到根据。
我也不会解释,哎,无语。

jdk api 里面没有说明,但是可以通过程序的执行来说明,事实。



谢谢 我在jdk api里面找到这种写法了哈……
3 楼 mars914 2012-07-03  
a455642158 写道
非常感谢……对于下面这段代码:
         MyThread1 mt = new MyThread1(); 
         Thread t1 = new Thread(mt,"一号窗口"); 
         Thread t2 = new Thread(mt,"二号窗口"); 
         Thread t3 = new Thread(mt,"三号窗口");
我们老大非常反感,说你这样写是错的,跟我说是在api里面找不到根据。
我也不会解释,哎,无语。

jdk api 里面没有说明,但是可以通过程序的执行来说明,事实。
2 楼 a455642158 2012-07-03  
非常感谢……对于下面这段代码:
         MyThread1 mt = new MyThread1(); 
         Thread t1 = new Thread(mt,"一号窗口"); 
         Thread t2 = new Thread(mt,"二号窗口"); 
         Thread t3 = new Thread(mt,"三号窗口");
我们老大非常反感,说你这样写是错的,跟我说是在api里面找不到根据。
我也不会解释,哎,无语。
1 楼 mars914 2012-05-03  
实现Runnable接口相对于继承Thread类来说,有如下显著的好处:
1.适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码、数据有效分离,较好地体现了面向对象的设计思想。
2.可以避免由于JAVA的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了。
3.有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程可以操作相同的数据,与它们的代码无关。当共享访问相同的对象时,即它们共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例。
事实上,几乎所有多线程应用都可以用实现Runnable接口的方式。


//上面所说的看得不是很明白,但大致从两个方面分析了两种实现多线程方法的区别,一就是资源共享,二就是java单继承的问题。

-------------------------------------------------------------------------------------

对于具有相同目标对象的线程,当其中一个线程享用CPU资源时,目标对象自动调用接口中的run()方法,这时run()方法中的局部变量被分配内存空间。当轮到另一个线程享用CPU资源时,目标对象会再次调用接口中的run()方法,那么run()方法中的局部变量会再次分配内存空间。也就是说,run()方法已经启动运行了两次,分别运行在不同的线程中,即运行在不同的时间片内。run()方法中的局部变量称为线程的局部变量。不同线程的run()方法中的局部变量互不干扰,一个线程改变了自己的run()方法中局部变量的值,不会影响其他线程的run()方法中的局部变量。

相关推荐

    Java中继承thread类与实现Runnable接口的比较

    主要介绍了Java中继承thread类与实现Runnable接口的比较的相关资料,需要的朋友可以参考下

    实现Runnable接口创建多线程.docx

    在Java中只支持单继承,因此通过继承Thread类创建线程有一定的局限性,这时可以使用另一种方式,即实现Runnable接口来创建线程。通过这种方式需要在Thread(Runnable target)的构造方法中,传递一个实现了Runnable...

    java多线程、通信机制、Thread类以及Runnable接口间的使用实例

    1. 写两个线程,一个线程打印1-52,另一个线程打印字母A-Z。打印顺序为12A34B56C……5152Z。 学习线程之间的通信协调关系。 2. 使用 runnable 接口实现按两... 使用继承Thread类方式和实现Runnable接口两种方式实现。

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口(csdn)————程.pdf

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口(csdn)————程

    Java中的Runnable接口最全讲义

    2.1 继承Thread类 2.2 实现Runnable接口 3. 实现Runnable接口: 3.1 实现步骤 3.2 优点与用途 4. 启动线程: 4.1 使用Thread类启动线程 4.2 使用Executor框架启动线程池 5. 传递参数给线程: 5.1 使用构造方法传递...

    java实现多线程的两种方式继承Thread类和实现Runnable接口的方法

    下面小编就为大家带来一篇java实现多线程的两种方式继承Thread类和实现Runnable接口的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    java 多线程Thread与runnable的区别

    主要介绍了java 多线程Thread与runnable的区别的相关资料,java线程有两种方法继承thread类与实现runnable接口,下面就提供实例帮助大家理解,需要的朋友可以参考下

    浅析Java中Runnable和Thread的区别

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;Thread类是在java.lang包中定义的。接下来通过本文给大家浅析Java中Runnable和Thread的区别,一起看看吧

    francistao#LearningNotes#Thread和Runnable实现多线程的区别1

    在第二种方法中,由于3个Thread对象共同执行一个Runnable对象中的代码,因此可能会造成线程的不安全,比如可能ticket会输出-1(如果我们Syste

    【Java多线程】Thread和Runnable创建新线程区别

    这是一道面试题,创建多线程时,使用继承Thread类和实现Runnable接口有哪些区别呢? 一、Thread 先来看看Thread类和其中的start()方法 class Thread implements Runnable{.....} // 可见,Thread类实现了Runnable...

    java多线程示例

    1.继承Thread类,重写run方法。Thread本质上也是一个实现了Runnable的实例,他代表一个线程的实例,并且启动线程的唯一方法就是通过Thread类的start方法。 2.实现Runnable接口,并实现该接口的run()方法.创建一个...

    100道常用必备java面试题-java基础

    使用`Thread`类或者`Runnable`接口实现创建一个线程。例如: ```java // 使用Thread类创建线程 Thread thread = new Thread() { public void run() { // 线程要执行的代码 } }; // 使用Runnable接口创建...

    JAVA多线程Thread和Runnable的实现

    java中实现多线程有两种方法:一种是继承Thread类,另一种是实现Runnable接口。

    Java中Runnable和Thread的区别分析

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口,下面就拉分别介绍一下这两种方法的优缺点

    java高并发相关知识点.docx

    线程:Java多线程的实现方式,包括继承Thread类和实现Runnable接口。 锁:Java中的锁机制,包括synchronized关键字和ReentrantLock类。 线程池:Java中的线程池机制,包括线程池的创建、执行任务、关闭等操作。 并发...

    java多线程学习

    java多线程学习,常见实现线程的方式,继承Thread类,实现Runnable接口,实现Callable接口

    Java中的线程Thread总结

     要注意的是Thread类也实现了Runnable接口,因此,从Thread类继承的类的实例也可以作为target传入这个构造方法。可通过这种方法实现多个线程的资源共享。  线程的生命周期:  1.新建状态(New):用new语句创建...

    JavaSE多线程

    Java是一门多线程语言。 进程:每一个软件运行,就会在操作系统中产生一...继承类与实现接口都 需要重写 run方法 ,线程需要完成的功能代码放在run 方法中。 线程的状态:新生状态、可运行状态、阻塞状态、死亡状态

    Java面试问题带答案40道.docx

    答:可以通过继承Thread类或实现Runnable接口来创建线程。另外,还可以使用Executor框架或线程池来管理线程。 3. Java中什么是抽象类? 答:抽象类是一种不能被实例化的类,只能作为其他类的基类。它可以包含抽象...

    基础深化和提高-Java多线程技术

    实现Runnable接口:创建一个类实现java.lang.Runnable接口,实现run()方法,并将该实现类传递给Thread类的构造函数中。然后创建Thread实例并启动线程。 java class MyRunnable implements Runnable { public void r

Global site tag (gtag.js) - Google Analytics