区别:Thread是类,而Runnable是接口。
抽象类和接口的区别如下:
① 在类来继承抽象类时,只需实现部分具体方法和全部抽象方法,而实现接口则要实现里面的全部方法。
②在接口中无成员变量,而抽象类中可有成员变量。
在Java中引进接口主要是为了解决多继承的问题。
实现多线程主要继承Thread 类和实现Runnable接口。
nable和thread的区别(多线程必须用Runable)
Java中有两种实现多线程的方式以及两种方式之间的区别。
看到一个面试题.问两种实现多线程的方法.没事去网上找了找答案. 。
网上流传很广的是一个网上售票系统讲解.转发过来.已经不知道原文到底是出自哪里了. 。
Java中有两种实现多线程的方式。一是直接继承Thread类,二是实现Runnable接口。那么这两种实现多线程的方式在应用上有什么区别呢?
为了回答这个问题,我们可以通过编写一段代码来进行分析。我们用代码来模拟铁路售票系统,实现通过四个售票点发售某日某次列车的100张车票,一个售票点用一个线程表示。
首先这样编写这个程序:
Java代码
class ThreadTest extends Thread{ 。
private int ticket = 100; 。
public void run(){ 。
while(true){ 。
if(ticket > 0){ 。
System.out.println(Thread.currentThread().getName() + 。
"is saling ticket" + ticket--); 。
}else{ 。
break; 。
}
}
}
}
源码打印?
class ThreadTest extends Thread{ 。
private int ticket = 100; 。
public void run(){ 。
while(true){ 。
if(ticket > 0){ 。
System.out.println(Thread.currentThread().getName() + 。
"is saling ticket" + ticket--); 。
}else{
break; 。
}
}
}
}
main测试类:
Java代码
public class ThreadDome1{ 。
public static void main(String[] args){ 。
ThreadTest t = new ThreadTest(); 。
t.start(); 。
t.start(); 。
t.start(); 。
t.start(); 。
}
}
源码打印?
public class ThreadDome1{ 。
public static void main(String[] args){ 。
ThreadTest t = new ThreadTest(); 。
t.start(); 。
t.start(); 。
t.start(); 。
t.start(); 。
}
}
上面的代码中,我们用ThreadTest类模拟售票处的售票过程,run方法中的每一次循环都将总票数减1,模拟卖出一张车票,同时该车票号打印出来,直接剩余的票数到零为止。在ThreadDemo1类的main方法中,我们创建了一个线程对象,并重复启动四次,希望通过这种方式产生四个线程。从运行的结果来看我们发现其实只有一个线程在运行,这个结果 告诉我们:一个线程对象只能启动一个线程,无论你调用多少遍start()方法,结果只有一个线程。
我们接着修改ThreadDemo1,在main方法中创建四个Thread对象:
Java代码
public class ThreadDemo1{ 。
public static void main(String[] args){ 。
new ThreadTest().start(); 。
new ThreadTest().start(); 。
new ThreadTest().start(); 。
new ThreadTest().start(); 。
}
}
源码打印?
public class ThreadDemo1{ 。
public static void main(String[] args){ 。
new ThreadTest().start(); 。
new ThreadTest().start(); 。
new ThreadTest().start(); 。
new ThreadTest().start(); 。
}
}
Java代码
class ThreadTest extends Thread{ 。
private int ticket = 100; 。
public void run(){ 。
while(true){ 。
if(ticket > 0){ 。
System.out.println(Thread.currentThread().getName() + 。
" is saling ticket" + ticket--); 。
}else{ 。
break; 。
}
}
}
}
源码打印?
class ThreadTest extends Thread{ 。
private int ticket = 100; 。
public void run(){ 。
while(true){ 。
if(ticket > 0){ 。
System.out.println(Thread.currentThread().getName() + 。
" is saling ticket" + ticket--); 。
}else{
break; 。
}
}
}
}
这下达到目的了吗?
从结果上看每个票号都被打印了四次,即 四个线程各自卖各自的100张票,而不去卖共同的100张票。这种情况是怎么造成的呢?我们需要的是,多个线程去处理同一个资源,一个资源只能对应一个对象,在上面的程序中,我们创建了四个ThreadTest对象,就等于创建了四个资源,每个资源都有100张票,每个线程都在独自处理各自的资源。
经过这些实验和分析,可以总结出,要实现这个铁路售票程序,我们只能创建一个资源对象,但要创建多个线程去处理同一个资源对象,并且每个线程上所运行的是相同的程序代码。在回顾一下使用接口编写多线程的过程。
Java代码
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(); 。
}
}
源码打印?
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(); 。
}
}
Java代码
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--); 。
}
}
}
}
源码打印?
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--); 。
}
}
}
}
上面的程序中,创建了四个线程, 每个线程调用的是同一个ThreadTest对象中的run()方法,访问的是同一个对象中的变量(tickets)的实例,这个程序满足了我们的需求。在Windows上可以启动多个记事本程序一样,也就是多个进程使用同一个记事本程序代码。
可见, 实现Runnable接口相对于继承Thread类来说,有如下显著的好处:
(1)适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码,数据有效的分离,较好地体现了面向对象的设计思想。
(2)可以避免由于Java的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了。
(3)有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程操作相同的数据,与它们的代码无关。当共享访问相同的对象是,即它们共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例。 Java中Runnable和Thread的区别更详细的资料参考:http://edu.51cto.com/course/course_id-4002.html。
java中有两种实现多线程的方式:
1. 一种是通过继承Thread类,同时重写run()方法。但是java中,只允许单继承,也就是一个类只能继承一个父类,使得该方式具有一定的局限性,等下就知道了。
2. 另一种是实现Runnable类接口的run()方法,再结合Thread类来实现多线程。
两种方式最终都是通过调用start()方法来实现多线程。切记不能直接调用Thread类或Runnable对象的run()方法,因为直接调用run()方法,只会执行同一个线程中的任务,而不会启动新线程。调用start()方法将会创建一个执行run()方法的线程。
Runnable和Thread区别。
实际开发中我们通常采用Runnable接口来实现多线程。因为实现Runnable接口比继承Thread类有如下好处:
1. 避免继承的局限,一个类可以继承多个接口,但是类只能继承一个类。
2. Runnable接口实现的线程便于资源共享。而通过Thread类实现,各自线程的资源是独立的,不方便共享。
java多线程中,Runnable就是上帝,Thread也是其子类,弱你没有直接去实现Runnable接口。
直接继承的是Thread,等价你间接实现了Runnable这个接口!。
区别:
直接继承Thread,比较单一,无法在继承别的类!。
如果去实现Runnable接口就不一样了,你还可以继承其他的类,也可以实现其他的接口,很灵活!。
统一:
都的重写run方法!
1 线程接口的实现有两种方式,第一:继承Thread类;第二:实现Runnnable接口;
2 两种创建方式上的不同:
建线程的第一种方式:继承Thread ,由子类复写run方法。
1,定义类继承Thread类;
2,目的是复写run方法,将要让线程运行的代码都存储到run方法中;
3,通过创建Thread类的子类对象,创建线程对象;
4,调用线程的start方法,开启线程,并执行run方法。
创建线程的第二种方式:实现一个接口Runnable。
1,定义类实现Runnable接口。
2,覆盖接口中的run方法(用于封装线程要运行的代码)。
3,通过Thread类创建线程对象;
4,将实现了Runnable接口的子类对象作为实际参数传递给Thread类中的构造函数。
3 下面是具体的代码展示两种方式创建线程:
继承Thread类创建线程的代码:
public class ThreadDemo {。
public static void main(String[] args) {。
// ThreadTest是继承了Thread类。
ThreadTest t1=new ThreadTest (" 1");。
t1.start();
//线程类 继承Thread类。
public class ThreadTest extends Thread {。
private int ticket=100;//每个线程都拥有100张票。
public ThreadTest (){}。
public ThreadTest (String name){。
super(name);
@Override
public void run() {。
while(ticket>0){。
System.out.println(Thread.currentThread().getName());。
实现Runnable 接口的方式:
class Person{ 。
private int sum; 。
public void add(int n){ 。
sum+=n;
System.out.println("sum="+sum); 。
}
}
//Person类实现Runnable接口。
class Person implements Runnable{ 。
private Person b=new Person (); 。
public void run(){ 。
synchronized(b){ 。
for(int x=0;x<3;x++) 。
{
b.add(100);
}
}
}
}
4 实际开发中一般使用Runnable接口的方式比较多,因为:
通过继承Thread类的方式,可以完成多线程的建立。但是这种方式有一个局限性,如果一个类已经有了自己的父类,就不可以继承Thread类。
而实现Runnable接口可以避免单继承的局限性。