すでに学んだことと思いますが、スレッドを走らせるには、二つの方法が
あります。第一の方法は、Threadクラスを継承したクラスを定義する
というやりかたです。第二の方法は、Runnable interface を実装したクラスを定義
するというものです。いずれの方法でも、スレッドの本体は、メソッド run のなかで
定義されることになります。
簡単なmulti-threaded なプログラムを見てみることにしましょう。 ここで基本となるスレッドは、Threadを継承した、Sample1 という名前のクラスの中 で定義されています。
class Sample1 extends Thread { public void run() { for( int i=1 ; i < 5 ; i++ ) { System.out.println( getName() + ": " + i + "; " ); } } public static void main(String args[]) { for (int i = 0; i < 3 ; i++) { new Sample1().start(); } } }
run で定義されているスレッドは、1から4までの数字を表示する だけです。getName()というメソッドは、スレッドの名前を返します。
main メソッドは、マルチ・スレッドのプログラムになっています。ここでは、 for ループが、コンストラクタ Sample1() を3回呼びますので、三つのスレッドが つくられ、それがstart()で起動されます。
このときの実行結果は次のようになります。
Thread-4: 1; Thread-4: 2; Thread-4: 3; Thread-4: 4; Thread-5: 1; Thread-5: 2; Thread-5: 3; Thread-5: 4; Thread-6: 1; Thread-6: 2; Thread-6: 3; Thread-6: 4:
この出力結果だけを見ると、まずThread-4が呼ばれて実行され、次に、 Thread-5,Thread-6が呼ばれて、それぞれのスレッドで、run が実行されたのでは、 と思うかも知れません。
実は、そうではありません。次のプログラムの出力を予想してみてください。 このSample2は、先のSample1に、プリント文を追加しただけです。
class Sample2 extends Thread { public void run() { for( int i=1 ; i < 5 ; i++ ) { System.out.println( getName() + ": " + i + "; " ); } } public static void main(String args[]) { for (int i = 0; i < 3 ; i++) { System.out.println( i + "; start" ); new Sample2().start(); } System.out.println( "end" ); } }
0; start 1; start 2; start end Thread-4: 1; Thread-4: 2; Thread-4: 3; Thread-4: 4; Thread-5: 1; Thread-5: 2; Thread-5: 3; Thread-5: 4; Thread-6: 1; Thread-6: 2; Thread-6: 3; Thread-6: 4;
少し予想が外れたと思います。 ここで大事なことは、メソッドstart()は、スレッドの実行を開始しますが、 その終了を待つわけではないというということです。start()は、ブロックせずに ただちに制御を返します。先の例では、forループもすぐに終了し、プログラム 自身はendを表示しています。しかし、3つのスレッドは、それから動き出します。