- 浏览: 429712 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
haoxuexi87:
【学途无忧网】Hive详解 ...
Hive详细配置手册 -
jamin415:
感觉楼主还没理解透彻,可以先看看源代码这两个类是怎么实现的,T ...
Java中继承thread类与实现Runnable接口的区别 -
hudazheng:
mars914 写道a455642158 写道非常感谢……对于 ...
Java中继承thread类与实现Runnable接口的区别 -
coolcgp:
博主用继承Thread用new,用Runnable时用共享,概 ...
Java中继承thread类与实现Runnable接口的区别 -
Koby丶:
flight2006 写道这篇文章举例和结论都没错,但是博主理 ...
Java中继承thread类与实现Runnable接口的区别
Java中线程的创建有两种方式:
1. 通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中
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)创建子类。
评论
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();
实现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一样
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
实现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你可以选择不共享。
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
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的。每一个线程一个资源
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
这样理解对不对?
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()方法吧
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接口的区别好不!
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(),"三号窗口");
这两种的区别主要还是接口和继承类的区别
MyThread1 mt = new MyThread1();
Thread t1 = new Thread(mt,"一号窗口");
Thread t2 = new Thread(mt,"二号窗口");
Thread t3 = new Thread(mt,"三号窗口");
我们老大非常反感,说你这样写是错的,跟我说是在api里面找不到根据。
我也不会解释,哎,无语。
jdk api 里面没有说明,但是可以通过程序的执行来说明,事实。
谢谢 我在jdk api里面找到这种写法了哈……
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();
Thread t1 = new Thread(mt,"一号窗口");
Thread t2 = new Thread(mt,"二号窗口");
Thread t3 = new Thread(mt,"三号窗口");
我们老大非常反感,说你这样写是错的,跟我说是在api里面找不到根据。
我也不会解释,哎,无语。
1.适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码、数据有效分离,较好地体现了面向对象的设计思想。
2.可以避免由于JAVA的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了。
3.有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程可以操作相同的数据,与它们的代码无关。当共享访问相同的对象时,即它们共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例。
事实上,几乎所有多线程应用都可以用实现Runnable接口的方式。
//上面所说的看得不是很明白,但大致从两个方面分析了两种实现多线程方法的区别,一就是资源共享,二就是java单继承的问题。
-------------------------------------------------------------------------------------
对于具有相同目标对象的线程,当其中一个线程享用CPU资源时,目标对象自动调用接口中的run()方法,这时run()方法中的局部变量被分配内存空间。当轮到另一个线程享用CPU资源时,目标对象会再次调用接口中的run()方法,那么run()方法中的局部变量会再次分配内存空间。也就是说,run()方法已经启动运行了两次,分别运行在不同的线程中,即运行在不同的时间片内。run()方法中的局部变量称为线程的局部变量。不同线程的run()方法中的局部变量互不干扰,一个线程改变了自己的run()方法中局部变量的值,不会影响其他线程的run()方法中的局部变量。
发表评论
-
java中的String类常量池详解
2012-05-04 16:47 1772String常量池详解: 1.String使用private ... -
Java 集合框架的体系
2012-05-02 20:42 2132一、概述 在Java语言中,Java语言的设计者对常用 ... -
八皇后算法详解
2012-03-15 18:14 25911.引子 中国有一句 ... -
java.lang.OutOfMemoryError异常解决方法
2012-03-08 14:52 29387原因:常见的有以下几种: 1.内存中加载的数据量过于庞大,如 ... -
String\StringBuilder\StringBuffer之间的区别
2012-03-04 21:11 68201、String类 String 本身的值是不能改变的 ... -
抽象类和接口的区别
2012-03-04 14:14 1205一、abstract 类 如果一个类中没有包含足够的信息来 ... -
Java基本数据类型
2012-02-06 19:20 1349基本类型,或者叫做内置类型,是JAVA中不同于类的特殊类型。它 ... -
Java的SPI机制
2011-11-29 13:34 3476SPI的全名为Service Provider Int ...
相关推荐
主要介绍了Java中继承thread类与实现Runnable接口的比较的相关资料,需要的朋友可以参考下
在Java中只支持单继承,因此通过继承Thread类创建线程有一定的局限性,这时可以使用另一种方式,即实现Runnable接口来创建线程。通过这种方式需要在Thread(Runnable target)的构造方法中,传递一个实现了Runnable...
1. 写两个线程,一个线程打印1-52,另一个线程打印字母A-Z。打印顺序为12A34B56C……5152Z。 学习线程之间的通信协调关系。 2. 使用 runnable 接口实现按两... 使用继承Thread类方式和实现Runnable接口两种方式实现。
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口(csdn)————程
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接口;Thread类是在java.lang包中定义的。接下来通过本文给大家浅析Java中Runnable和Thread的区别,一起看看吧
在第二种方法中,由于3个Thread对象共同执行一个Runnable对象中的代码,因此可能会造成线程的不安全,比如可能ticket会输出-1(如果我们Syste
这是一道面试题,创建多线程时,使用继承Thread类和实现Runnable接口有哪些区别呢? 一、Thread 先来看看Thread类和其中的start()方法 class Thread implements Runnable{.....} // 可见,Thread类实现了Runnable...
1.继承Thread类,重写run方法。Thread本质上也是一个实现了Runnable的实例,他代表一个线程的实例,并且启动线程的唯一方法就是通过Thread类的start方法。 2.实现Runnable接口,并实现该接口的run()方法.创建一个...
使用`Thread`类或者`Runnable`接口实现创建一个线程。例如: ```java // 使用Thread类创建线程 Thread thread = new Thread() { public void run() { // 线程要执行的代码 } }; // 使用Runnable接口创建...
java中实现多线程有两种方法:一种是继承Thread类,另一种是实现Runnable接口。
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口,下面就拉分别介绍一下这两种方法的优缺点
线程:Java多线程的实现方式,包括继承Thread类和实现Runnable接口。 锁:Java中的锁机制,包括synchronized关键字和ReentrantLock类。 线程池:Java中的线程池机制,包括线程池的创建、执行任务、关闭等操作。 并发...
java多线程学习,常见实现线程的方式,继承Thread类,实现Runnable接口,实现Callable接口
要注意的是Thread类也实现了Runnable接口,因此,从Thread类继承的类的实例也可以作为target传入这个构造方法。可通过这种方法实现多个线程的资源共享。 线程的生命周期: 1.新建状态(New):用new语句创建...
Java是一门多线程语言。 进程:每一个软件运行,就会在操作系统中产生一...继承类与实现接口都 需要重写 run方法 ,线程需要完成的功能代码放在run 方法中。 线程的状态:新生状态、可运行状态、阻塞状态、死亡状态
答:可以通过继承Thread类或实现Runnable接口来创建线程。另外,还可以使用Executor框架或线程池来管理线程。 3. Java中什么是抽象类? 答:抽象类是一种不能被实例化的类,只能作为其他类的基类。它可以包含抽象...
实现Runnable接口:创建一个类实现java.lang.Runnable接口,实现run()方法,并将该实现类传递给Thread类的构造函数中。然后创建Thread实例并启动线程。 java class MyRunnable implements Runnable { public void r