Javaの勉強をはじめると、突然「スレッド」「マルチスレッド」という言葉が出てくる。
特にJavaを勉強し始めたばかりの初心者の方は、困惑するだろう。
率直に言って、エンジニアの入り口付近ですぐに使う機会はないので読み飛ばしても構わないが、概念だけでも理解しておくと役に立つこともあるだろう。また、数年後には実際に使う機会がどこかで来るはずだ。
このページではスレッドとJavaのマルチスレッド処理について簡単に理解できるようにまとめた。参考にしてほしい。
目次
そもそもスレッドとは?
スレッドとは「thread」で、もともとは「糸、筋道、脈絡」という意味をもつ言葉だ。
プログラミングの分野では処理を実行する流れの単位をスレッドと呼ぶ。
プログラムのソースコードをペンで追っていくと、処理の初めから終わりまでが一本の糸のような線であらわされる。このような一本の糸であらわされる処理の流れをスレッドと呼ぶ。
大変大雑把な例えだが、スレッドを1つの役割をもった人間と考えるとわかりやすいだろう。
リンゴを買うという役割をもった人間がいるとする。
スーパーへ入る
↓
リンゴ売り場へ行く
↓
リンゴを選ぶ
↓
レジで購入する
↓
スーパーを出る
この一連の動きをスレッドと考えるとイメージがしやすいかと思う。
マルチスレッド
マルチスレッドとは?
先に書いたリンゴを買う人のように、1つの処理だけで終わるプログラムをシングルスレッドのプログラムと呼ぶ。
しかし、実際にはいくつかの処理を並行して行う。要するに、複数のスレッドが同時に動くことになる。
このように複数のスレッドが同時に動くことをマルチスレッドという。
スーパーに様々なものを買う役目をもった人間がいるようなものだ。
大分簡易化されているが図で表すと次のようになる。
マルチスレッドを使う理由は?
1人の人間がたくさんの物を買うよりも、複数の人間がそれぞれ目的のものを1つ買うほうが早い。
同じように、1つのスレッドで処理を行っていくよりも、マルチスレッドでの作業速度は速くなる。正確には速くならない場合もあって複雑なのだが、速くできる可能性があると思っておけば良い。
また、例えばWordなどでは入力中、同時にスペルチェックが行われていたりする。このように同時進行させられるのが、マルチスレッドの真骨頂だ。
ブラウザなどでも、どこかへのリンクボタンを押して、「やっぱりやめた」と他のリンクを押すことができるだろう。シングルスレッドだと通信中は他のことができない。しかし、マルチスレッドにしておくと途中で処理を中断したり、別のページにジャンプすることができる。
Javaでのスレッド
Javaはマルチスレッドに対応した言語だ。
Java言語で用意している様々なクラスにマルチスレッドに対応した処理が組み込んであり、プログラムを作成する際決まり事を守りさえすれば、複雑なことを意識しなくても自動的にある程度は安全に実行してくれるように設計されている。
Javaでは、スレッドの実装に2つの方法を用意している。
1. Threadクラスを利用
Threadクラスを継承して使うパターンだ。
extends Thread
単純な処理を行う場合に使用する。
java.lang.Threadクラスを継承してサブクラスを作成し、そこへ実現したい処理を記述する。
スレッドのサンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class ThreadSample1 extends Thread{ // [1] public static void main(String[] args) { // [2] ThreadSample1 sample1 = new ThreadSample1(); // [3] sample1.start(); // [4] for (int i = 0; i < 10; i++) { System.out.println("mainメソッドでの処理 = " + i); } } @Override public void run(){ // [5] for (int r = 0; r < 10; r++) { System.out.println("runメソッドでの処理" + r); } } |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
mainメソッドでの処理 = 0 mainメソッドでの処理 = 1 mainメソッドでの処理 = 2 runメソッドでの処理0 runメソッドでの処理1 mainメソッドでの処理 = 3 runメソッドでの処理2 runメソッドでの処理3 runメソッドでの処理4 runメソッドでの処理5 mainメソッドでの処理 = 4 mainメソッドでの処理 = 5 mainメソッドでの処理 = 6 mainメソッドでの処理 = 7 mainメソッドでの処理 = 8 mainメソッドでの処理 = 9 runメソッドでの処理6 runメソッドでの処理7 runメソッドでの処理8 runメソッドでの処理9 |
注:結果は、実行するコンピューターによって異なります。
Threadクラスを利用したサンプルコードの説明
サンプルコードの中身は次のようになっている。
- [1] Threadクラスの継承(Java言語で用意しているThreadクラスの機能を利用すること)を宣言
- [2]メインメソッド→このプログラムのスタート地点。
- [3]ThreadSample1クラスのインスタンスを生成する。
- [4]スレッドを起動する。
- [5]継承したThreadクラスにあるrunメソッドを上書き(オーバーライド)する。スレッドの実行開始点となる。runメソッドが書かれていない場合には、スーパークラスThreadのrunメソッドが自動的に呼び出されて実行される。
2. Runnableインターフェースを利用
2つ目はRunnnalbeインターフェースを利用するパターンだ。
implements Runnable Runnable
複雑な処理を行う場合に使用する。
java.lang.Runnableインターフェースを実装するクラスを作成し、そこへ実現したい処理を記述する。
Runnnalbeインターフェースのサンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class ThreadSample2 implements Runnable{// [1] public static void main(String[] args) {// [2] ThreadSample2 sample2 = new ThreadSample2(); // [3] Thread thread = new Thread(sample2); // [4] thread.start();// [5] for (int i = 0; i < 10; i++) { System.out.println("mainメソッドでの処理 = " + i); } } @Override public void run(){ // [6] for (int r = 0; r < 10; r++) { System.out.println("runメソッドでの処理" + r); } } |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
mainメソッドでの処理 = 0 mainメソッドでの処理 = 1 mainメソッドでの処理 = 2 mainメソッドでの処理 = 3 runメソッドでの処理0 runメソッドでの処理1 runメソッドでの処理2 runメソッドでの処理3 runメソッドでの処理4 runメソッドでの処理5 runメソッドでの処理6 runメソッドでの処理7 runメソッドでの処理8 runメソッドでの処理9 mainメソッドでの処理 = 4 mainメソッドでの処理 = 5 mainメソッドでの処理 = 6 mainメソッドでの処理 = 7 mainメソッドでの処理 = 8 mainメソッドでの処理 = 9 |
注:結果は、実行するコンピューターによって異なります。
Runnableインターフェースを利用したサンプルコードの説明
サンプルコードの中身は次のようになっている。
- [1]Runnableインターフェースを実装(Java言語で用意しているRunnableインターフェースの決まりにしたがってクラスを作成)する宣言
- [2]メインメソッド→このプログラムのスタート地点。
- [3]ThreadSample2クラスのインスタンスを作成する。
- [4]Threadクラスのインスタンスを作成する。
- [5]スレッドを起動する。
- [6]Runnableインターフェースにあるrunメソッドを上書き(オーバーライド)する。スレッドの実行開始点。Runnableインターフェースを実装するクラスでは、必ずrunメソッドをオーバーライドしなければならない。
2つの方法の違い
簡単なのは1のThreadクラスを利用する方法だろう。
しかし、Javaではスーパクラスは1つしか持つことができない。そのために用意されているのがRunnableインターフェースだ。
やりたいことが複雑になると様々なクラスを階層にわけて作らなくてはいけないが、そのような場合に、どの階層の位置にあってもRunnableインターフェースを実装することによりスレッドを作ることができる。
マルチスレッドの注意点
マルチスレッドでは複数のスレッドが動く。しかし、まったく別々に動くのではなく同じ処理を利用したりする場合もある。
そのような時に注意しないと、Aの結果がBの結果で上書きされたり、内容が混在したりとこんがらがった糸のようにもつれてしまう。
そのようなことを避けるために、処理を行わずに待たせたり(排他)処理のタイミングを合わせたり(同期)する仕組みが用意されている。
ここの辺りをしっかりと使いこなせるようになってから、マルチスレッドを組み込んでいくのがいいだろう。
まとめ
このページではスレッドの説明とJavaでのマルチスレッドの活用を簡単にまとめてみた。いかがだっただろうか?
なかなかすぐに使いこなせるものではないが、将来必ず役に立つ機会が来るはずだ。概念やメリットだけでも理解をしていってほしい。
コメント