众所周知Java多线程通过两种方式创建:一种是继承Thread类,另一种是实现Runnable接口。那么,两种方式有什么区别?哪种方式更好些?
Thread类定义在Java.lang包中,只要继承Thread类同时覆写本类的run()方法就能操作多线程,但一个类只能继承一个父类,这是继承Thread类的局限。
Thread类示例:
class Test extends Thread{
private String name;
public Test(String name){
super();
this.name = name;
}
public void run(){
for(int i=0;i<10;i++){
System.out.println("线程启动:"+this.name+",i="+i);
}
}
}
public class ThreadTest{
public static void main(String[] args){
Test t1=new Test("线程A");
Test t2=new Test("线程B");
t1.run();
t2.run();
}
}
结果很有规律,第一个对象先执行,然第二个对象再执行,并没有相互交替运行,说明线程没启用,只是普通的方法调用。查看JDK文档发现一旦调用start()方法,则通过JVM找到run()方法启动线程。
public class ThreadTest{
public static void main(String[] args){
Test t1=new Test("线程A");
Test t2=new Test("线程B");
t1.start();
t2.start();
}
}
这样程序能正常完成交互式运行,为什么非要使用start()方法启动多线程?
在JDK安装目录下,src.zip是Java源程序,通过此找到Thread类的start()方法的定义,发现使用private native void start();其中native关键字表示允许调用操作系统的底层函数,这样的技术称为JNI技术(Java Native Interface)。
Runnabl接口示例:
实际开发中多线程操作较少使用Thread类,主要通过Runnable接口完成。
class Test implements Runnable{
private String name;
public Test(String name){
this.name = name;
}
public void run(){
for(int i=0;i<10;i++){
System.out.println("线程启动:"+this.name+",i="+i);
}
}
}
public class RunnableTest{
public static void main(String[] args){
Test t1 = new Test("线程1");
Test t2 = new Test("线程2");
new Thread(t1).start();
new Thread(t2).start();
}
}
使用Runnable接口定义的子类没有start()方法,只有Thread类中才有。通过JDK文档查看Thread类有一构造方法:Public Thread(Runnable targer)接受Runnable的子类实例,也就是说通过Thread类启动start()方法实现Runnable的多线程。
两种实现方式的区别和联系:
程序开发中多线程永远以实现Runnable接口为主,因为和继承Thread类相比有如下好处:
1、避免单继承的局限,Java中一个类允许实现多个接口;
2、适合于资源的共享。
Thread类卖票程序:
class Ticket extends Thread{
private int tick=10;
public void run(){
while(true){
if(tick>0)
System.out.println(Thread.currentThread().getName()+"...SaleTikcet...."+tick--);
}
}
}
class TicketDemo{
public static void main(String[] args) {
Ticket t1 = new Ticket();
Ticket t2 = new Ticket();
Ticket t3 = new Ticket();
t1.start();//每个线程都各卖10张,共计30张票,
t2.start();//实际只有10张票,每个线程都各卖各的,
t3.start();//没有达到资源共享目的。
}
}
如果用Runnable接口就能实现资源共享,示例如下:
class Ticket implements Runnable{
private int tick = 10;
public void run(){
while(true){
if(tick>0)
{
System.out.println(Thread.currentThread().getName()+"...SaleTicket..."+tick--);
}
}
}
}
class TicketDemo2{
public static void main(String[] args){
Ticket t = new Ticket();
new Thread(t).start();//同一t,在Thread类中不可以,
new Thread(t).start();//如果同一个实例化对象,会报异常。
new Thread(t).start();
}
}
现在程序中有三个线程,但一共只卖了10张票,达到了资源共享目的。
通过查看JDK文档发现:public class Thread extends Object implements Runnable ,说明Thread类也是Runnable接口的子类。