Java中实现多线程的两种方式之间的区别

Java提供了线程类Thread来建立多线程的程序。其实,建立线程与建立普通的类的对象的操做是同样的,而线程就是Thread类或其子类的实例对象。每一个Thread对象描述了一个单独的线程。要产生一个线程,有两种方法:html

    ◆须要从Java.lang.Thread类派生一个新的线程类,重载它的run()方法; 
    ◆实现Runnalbe接口,重载Runnalbe接口中的run()方法。java

  为何Java要提供两种方法来建立线程呢?它们都有哪些区别?相比而言,哪种方法更好呢?多线程

  在Java中,类仅支持单继承,也就是说,当定义一个新的类的时候,它只能扩展一个外部类.这样,若是建立自定义线程类的时候是经过扩展 Thread类的方法来实现的,那么这个自定义类就不能再去扩展其余的类,也就没法实现更加复杂的功能。所以,若是自定义类必须扩展其余的类,那么就可使用实现Runnable接口的方法来定义该类为线程类,这样就能够避免Java单继承所带来的局限性。ide

  还有一点最重要的就是使用实现Runnable接口的方式建立的线程能够处理同一资源,从而实现资源的共享.post

  一、经过扩展Thread类来建立多线程this

  假设一个影院有三个售票口,分别用于向儿童、成人和老人售票。影院为每一个窗口放有100张电影票,分别是儿童票、成人票和老人票。三个窗口须要同时卖票,而如今只有一个售票员,这个售票员就至关于一个CPU,三个窗口就至关于三个线程。经过程序来看一看是如何建立这三个线程的。spa

 
  1. public class MutliThreadDemo {  
  2.     public static void main(String[] args) {  
  3.         MutliThread m1=new MutliThread("Window 1");   
  4.         MutliThread m2=new MutliThread("Window 2");   
  5.         MutliThread m3=new MutliThread("Window 3");   
  6.         m1.start();  
  7.         m2.start();  
  8.         m3.start();  
  9.     }  
  10. }  

 

 
  1. public class MutliThread extends Thread {  
  2.     private int ticket=100;//每一个线程都拥有100张票   
  3.   
  4.     public MutliThread (){}  
  5.     public MutliThread (String name){  
  6.         super(name);  
  7.     }  
  8.       
  9.     @Override  
  10.     public void run() {  
  11.         while(ticket>0){   
  12.             System.out.println(ticket--+" is saled by "+Thread.currentThread().getName());   
  13.         }   
  14.     }  
  15. }  

 

程序中定义一个线程类,它扩展了Thread类。利用扩展的线程类在MutliThreadDemo类的主方法中建立了三个线程对象,并经过start()方法分别将它们启动。.net

从结果能够看到,每一个线程分别对应100张电影票,之间并没有任何关系,这就说明每一个线程之间是平等的,没有优先级关系,所以都有机会获得CPU的处理。可是结果线程

显示这三个线程并非依次交替执行,而是在三个线程同时被执行的状况下,有的线程被分配时间片的机会多,票被提早卖完,而有的线程被分配时间片的机会比较设计

少,票迟一些卖完。

  可见,利用扩展Thread类建立的多个线程,虽然执行的是相同的代码,但彼此相互独立,且各自拥有本身的资源,互不干扰。

 

  二、经过实现Runnable接口来建立多线程

 
  1. public class MutliThreadDemo {  
  2.     public static void main(String[] args) {  
  3.         MutliThread m1=new MutliThread("Window 1");   
  4.         MutliThread m2=new MutliThread("Window 2");   
  5.         MutliThread m3=new MutliThread("Window 3");   
  6.         Thread t1=new Thread(m1);   
  7.         Thread t2=new Thread(m2);   
  8.         Thread t3=new Thread(m3);   
  9.         t1.start();   
  10.         t2.start();   
  11.         t3.start();   
  12.     }  
  13. }  

 

 
  1. public class MutliThread implements Runnable{   
  2.     private int ticket=100;//每一个线程都拥有100张票   
  3.     private String name;   
  4.     MutliThread(String name){   
  5.         this.name=name;   
  6.     }   
  7.     public void run(){   
  8.         while(ticket>0){   
  9.             System.out.println(ticket--+" is saled by "+name);   
  10.         }   
  11.     }   
  12. }  

 

因为这三个线程也是彼此独立,各自拥有本身的资源,即100张电影票,所以程序输出的结果和 1 结果大同小异。均是各自线程对本身的100张票进行单独的处理,互不影响。

  可见,只要现实的状况要求保证新建线程彼此相互独立,各自拥有资源,且互不干扰,采用哪一个方式来建立多线程都是能够的。由于这两种方式建立的多线程程序可以实现相同的功能。

 

  三、经过实现Runnable接口来实现线程间的资源共享

   现实中也存在这样的状况,好比模拟一个火车站的售票系统,假如当日从A地发往B地的火车票只有100张,且容许全部窗口卖这100张票,那么每个窗口也至关于一个线程,可是这时和前面的例子不一样之处就在于全部线程处理的资源是同一个资源,即100张车票。若是还用前面的方式来建立线程显然是没法实现的,这种状况该怎样处理呢?看下面这个程序,程序代码以下所示:

 
  1. public class MutliThreadDemo {  
  2.     public static void main(String[] args) {  
  3.         MutliThread m=new MutliThread();   
  4.         Thread t1=new Thread(m);   
  5.         Thread t2=new Thread(m);   
  6.         Thread t3=new Thread(m);   
  7.         t1.start();   
  8.         t2.start();   
  9.         t3.start();   
  10.     }  
  11. }  

 

 
  1. public class MutliThread implements Runnable{   
  2.     private int ticket=100;//每一个线程都拥有100张票   
  3.     public void run(){   
  4.         while(ticket>0){   
  5.             System.out.println(ticket--+" is saled by "+Thread.currentThread());   
  6.         }   
  7.     }   
  8. }  

 

结果正如前面分析的那样,程序在内存中仅建立了一个资源,而新建的三个线程都是基于访问这同一资源的,而且因为每一个线程上所运行的是相同的代码,所以它们执行的功能也是相同的。

  可见,若是现实问题中要求必须建立多个线程来执行同一任务,并且这多个线程之间还将共享同一个资源,那么就可使用实现Runnable接口的方式来建立多线程程序。而这一功能经过扩展Thread类是没法实现的,读者想一想看,为何?

  实现Runnable接口相对于扩展Thread类来讲,具备无可比拟的优点。这种方式不只有利于程序的健壮性,使代码可以被多个线程共享,并且代码和数据资源相对独立,从而特别适合多个具备相同代码的线程去处理同一资源的状况。这样一来,线程、代码和数据资源三者有效分离,很好地体现了面向对象程序设计的思想。所以,几乎全部的多线程程序都是经过实现Runnable接口的方式来完成的。