Javaスレッドを作成する2つの方法

12206 ワード

JavaはスレッドクラスThreadを提供してマルチスレッドのプログラムを作成する.実際には、スレッドの作成は通常のクラスのオブジェクトの作成と同じですが、スレッドはThreadクラスまたはそのサブクラスのインスタンスオブジェクトです.各Threadオブジェクトは、個別のスレッドを記述する.スレッドを生成するには、次の2つの方法があります.
◆Java.lang.Threadクラスから新しいスレッドクラスを派生させ、run()メソッドを再ロードする必要がある.◆Runnalbeインタフェースを実現し、Runnalbeインタフェースのrun()メソッドを再ロードする.
なぜJavaはスレッドを作成するために2つの方法を提供しますか?どのような違いがありますか?それに比べて、どちらの方法がいいですか?
Javaでは、クラスは単一継承のみをサポートしています.つまり、新しいクラスを定義すると、外部クラスは1つしか拡張できません.これにより、カスタムスレッドクラスを作成する際にThreadクラスを拡張する方法で実現されると、このカスタムクラスは他のクラスを拡張することができず、より複雑な機能を実現することができません.したがって、カスタムクラスが他のクラスを拡張する必要がある場合は、Runnableインタフェースを実装する方法を使用してクラスをスレッドクラスとして定義することができ、Java単一継承による限界を回避することができます.
もう一つ重要なのは、Runnableインタフェースを実現する方法で作成されたスレッドが同じリソースを処理することで、リソースの共有を実現することである.
1.Threadクラスを拡張してマルチスレッドを作成する
1つの映画館に3つの切符売り場があり、それぞれ子供、大人、老人に切符を売るために使われていると仮定します.映画館は窓口ごとに100枚の映画の切符を置いて、それぞれ子供の切符、大人の切符と老人の切符です.3つのウィンドウは同時に切符を売る必要がありますが、現在は1人の車掌しかいません.この車掌はCPUに相当し、3つのウィンドウは3つのスレッドに相当します.この3つのスレッドをどのように作成したかをプログラムで見てみましょう.
 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クラスのマスターメソッドに3つのスレッドオブジェクトを作成し、start()メソッドでそれぞれ起動します.
その結果,各スレッドはそれぞれ100枚の映画チケットに対応しており,何の関係もないことから,各スレッド間は平等で優先度関係がないことを示しており,CPUの処理を得る機会がある.でも結果は
この3つのスレッドが順次交互に実行されるのではなく,3つのスレッドが同時に実行される場合,あるスレッドはタイムスライスが割り当てられる機会が多く,チケットが事前に売り切れ,あるスレッドはタイムスライスが割り当てられる機会が比較されることを示した.
少なくて、切符は少し遅れて売り切れました.
拡張Threadクラスを用いて作成された複数のスレッドは,同じコードを実行しているが,互いに独立しており,それぞれが独自のリソースを持ち,互いに干渉していないことがわかる.
 
2.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 }

この3つのスレッドも互いに独立しており,それぞれ独自のリソース,すなわち100枚の映画チケットを持っているため,プログラム出力の結果は1の結果と大きく異なる.いずれもそれぞれのスレッドが自分の100枚のチケットを個別に処理し,互いに影響を及ぼさない.
現実的な状況が新しいスレッドが互いに独立し、それぞれがリソースを持ち、互いに干渉しないことを保証することを要求すれば、どの方法でマルチスレッドを作成してもよいことがわかる.この2つの方法で作成されたマルチスレッドプログラムは同じ機能を実現できるからである.
 
3、Runnableインタフェースを実現することによってスレッド間の資源共有を実現する
 例えば、ある駅の切符販売システムをシミュレートして、A地からB地への当日の切符が100枚しかなく、すべての窓口でこの100枚の切符を販売することが許可されている場合、各窓口も1つのスレッドに相当するが、この場合、前の例とは異なる点は、すべてのスレッドが処理するリソースが同じリソースである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 }

その結果、前に分析したように、プログラムはメモリに1つのリソースしか作成しませんでしたが、新しい3つのスレッドは同じリソースにアクセスすることに基づいており、各スレッドで同じコードが実行されているため、実行する機能も同じです.
現実的な問題で同じタスクを実行するために複数のスレッドを作成する必要があり、複数のスレッド間で同じリソースを共有する必要がある場合は、Runnableインタフェースを実装する方法でマルチスレッドプログラムを作成することができます.この機能はThreadクラスを拡張することでは実現できませんが、読者は考えてみてください.なぜですか.
Runnableインタフェースの実装は、拡張Threadクラスに比べて比類のない利点を有する.この方法は、プログラムの堅牢性に有利であるだけでなく、コードを複数のスレッドで共有することができ、コードとデータリソースが相対的に独立しているため、同じコードを有する複数のスレッドが同じリソースを処理する場合に特に適している.これにより,スレッド,コード,データリソースの3つが有効に分離され,オブジェクト向けプログラム設計の考え方がよく体現される.したがって,ほとんどのマルチスレッドプログラムはRunnableインタフェースを実装することによって達成される.