シリーズ一覧
[Java Gold対策] はじめてのスレッド 1日目 : スレッドとは?
[Java Gold対策] はじめてのスレッド 2日目 : スレッドの作り方
[Java Gold対策] はじめてのスレッド 3日目 : スレッドの作り方2
[Java Gold対策] はじめてのスレッド <よりみち1> : 匿名クラスで書く。
[Java Gold対策] はじめてのスレッド <よりみち2> : ラムダ式で書く。
[Java Gold対策] はじめてのスレッド 4日目 : スレッドをsleepさせよう
[Java Gold対策] はじめてのスレッド 5日目 : joinメソッドで順番待ち
[Java Gold対策] はじめてのスレッド 6日目 : runメソッドで条件付き停止
スレッドの作り方は2種類
前回は、スレッドとはなにかを理解しました。
では、シングルスレッドからマルチスレッドにするには、
つまり、スレッドを新たに作るにはどうすればいいのでしょうか?
具体的なコードを打ってみながら、理解していきましょう!
- Threadクラスを継承した新しいクラスを作る
- Runnableインターフェイスを実装した新しいクラスを作る
スレッドの作り方は、この2種類です。
今回は「1」のThreadクラスを継承したクラスを作り、拡張する方法を見ていきましょう!
Threadクラスを拡張する
スレッドの基本の作り方
- java.langパッケージのThreadクラスのインスタンスを生成する
- そのインスタンスの「startメソッド」を呼び出す
この部分のみコードにするとこのようになります。
Thread t = new Thread(); // ステップ1
t.start(); //ステップ2
これで、スレッドが完成しました!
しかし、インスタンスを生成した元のThreadクラスには、「実際に実行する命令がなにもない」ので、今完成したスレッドは「なにも処理を行わないスレッド」です。
続いて、新しく作成したスレッドで、実際に処理を実行させる方法を見ていきましょう。
実行したい処理を含めたスレッドの作り方
- Threadクラスを継承するクラスを宣言
- runメソッドをオーバーライドして実行したい命令を追加する
- startメソッドを呼び出す <注意!>
public class SampleThread extends Thread { // ステップ1
public void run() { // ステップ2
~実際に実行したい命令~
}
}
ステップ2でオーバーライドしたrunメソッドは、Threadクラスに定義されているメソッドです。
そのrunメソッド内部に実際の処理を書くことによって、それを実行するためのスレッドを作ることができます。
ステップ3は、注意が必要です!
実際に処理を書いたrunメソッドをいきなり呼び出すのではなく、あくまでもstartメソッドを呼び出して、スレッドを作成します。
すると、内部的にrunメソッドが呼び出され、処理が実行されます。
では、具体的なコードでポイントを確認していきましょう!
具体的に見てみる
SampleThreadというクラスを宣言し、マルチスレッドで処理を行うプログラムです。
// SampleThreadMain1.java
//ステップ1 Threadクラスを継承
class SampleThread1 extends Thread {
// ステップ2 runメソッドをオーバーライド
public void run() {
// 実際に実行したい命令:runメソッド内で出力を100回繰り返す
for(int i = 0; i < 100; i++) {
System.out.println("SampleThread1のrunメソッド(" + i + ")");
}
}
}
public class SampleThreadMain1 {
public static void main(String[] args) {
// スレッドを作る
SampleThread1 t = new SampleThread1();
// ステップ3 start
t.start();
// mainメソッド内で出力を100回繰り返す
for (int i = 0; i < 100; i++) {
System.out.println("SimpleThreadMain1のmainメソッド(" + i + ")");
}
}
}
このコードでは、Mainクラスのmainメソッドから、スレッドを作成して、別々の処理を行っています。
具体的には、Mainクラスのmainメソッドのスレッドと、SampleThreadクラスのrunメソッドのスレッドの、2つのスレッドが走っています。
実行結果: 2つのスレッドが同時に実行されます。
// 略 //
SampleThread1のrunメソッド(7)
SampleThreadMain1のmainメソッド(53)
SampleThreadMain1のmainメソッド(54)
SampleThread1のrunメソッド(8)
SampleThread1のrunメソッド(9)
SampleThread1のrunメソッド(10)
SampleThreadMain1のmainメソッド(55)
SampleThreadMain1のmainメソッド(56)
SampleThreadMain1のmainメソッド(57)
SampleThread1のrunメソッド(11)
SampleThreadMain1のmainメソッド(58)
SampleThreadMain1のmainメソッド(59)
// 略 //
結果を見ると分かる通り、2つのスレッドが交互に実行されるわけではありません。
最初からあるmainメソッドのスレッドと、あとから追加したrunメソッドのスレッドは、それぞれのペースで処理が進んでいきます。
各スレッドがどのタイミングで処理を行うかは、管理できません。
そのため、実行結果は毎回異なります。
この「はじめてのスレッド」後半戦では、この処理を制御する方法にも触れていきます。
ぜひ楽しみにしていてください!
この方法の問題点
晴れて、マルチスレッドプログラムを動かすことができましたね!
しかし、このThreadクラスを拡張するという方法には問題点があります。
それは「Threadを継承したクラスが、他のクラスを継承できない」という点です。
今回の例でいうと、SampleThreadクラスが、Threadクラス以外のクラスを継承することができないということです。
御存知の通り、Javaでは多重継承が禁止されています。
そのため、同じようなスレッドを複数作りたいときなどに、継承関係で量産していくことができなくなってしまうのです。
では、どうしたらよいのでしょうか?
そう、インターフェイスを実現する形にすればいいのです!
というわけで、次回はスレッドの作り方「2」のRunnableインターフェイスを実装する方法を見ていきましょう!
今日のキーワード
- Threadクラス :java.langパッケージ内のクラス。run/startメソッドが定義されている。
- startメソッド :新しいスレッドを作る
- runメソッド :処理を実行する