目次
スレッド(Thread)とは?
プログラミングで使われるスレッドとは、プログラムの中の処理のはじめから終わりまでのひとまとまりの単位のことを指します。
このスレッドの処理が単一で行われることをシングルスレッドと言います。
マルチスレッド(Multithread)とは?
一方で、複数のスレッドが同時並行して動くことをマルチスレッドと言います。
実際のプログラムでは、マルチスレッドで動いてることが多いでしょう。
マルチスレッドはどんな時に使うの?
例えば、ブラウザのリンクをクリックした後、「やっぱり別のリンク先を見よう」と思った時に、リンク先を読み込んでいる最中でもリンクを押すことが可能ですよね。
これは、マルチスレッドだからできることで、シングルスレッドだと読み込み中に他の動作は受け付けません。
また、Wordでも文章を書いている途中に誤字やスペルチェックが行われていますよね?
あれも、マルチスレッドで同時並行して処理を行っているからです。
Javaのスレッド・マルチスレッドの使い方
Javaのスレッド処理はどのように記述するのでしょうか?
ここでは、実際にプログラムを組んで確認してみましょう。スレッドには、Threadクラスを継承したクラスを使うパターンと、Runnableインターフェースを使うパターンがあります。
Threadクラスの使い方
Threadクラスを継承したサブクラスを作る場合は、以下のように記述します。
class サブクラス名 extends Thread { public void run() { // ここに処理を書きます } }
サンプルコードは以下の通りです。
public class Main { public static void main(String[] args) { MultiThread mt = new MultiThread(); mt.start(); for (int i = 0; i < 3; i++) { System.out.println("mainスレッド" + (i + 1) + "回目の処理"); } } } class MultiThread extends Thread { public void run() { for (int i = 0; i < 3; i++) { System.out.println("MultiThreadスレッド" + (i + 1) + "回目の処理"); } } }
実行結果
MultiThreadスレッド1回目の処理 mainスレッド1回目の処理 MultiThreadスレッド2回目の処理 mainスレッド2回目の処理 MultiThreadスレッド3回目の処理 mainスレッド3回目の処理
Runnableインターフェースの使い方
Runnableインターフェースを使う場合は、以下のように記述します。
class クラス名 implements Runnable { public void run() { // ここに処理を書きます } }
サンプルコードは以下の通りです。
public class Main { public static void main(String[] args) { MultiThread mt = new MultiThread(); Thread thread = new Thread(mt); thread.start(); for (int i = 0; i < 10; i++) { System.out.println("mainスレッド" + (i + 1) + "回目の処理"); } } } class MultiThread implements Runnable { public void run() { for (int i = 0; i < 10; i++) { System.out.println("MultiThreadスレッド" + (i + 1) + "回目の処理"); } } }
実行結果
MultiThreadスレッド1回目の処理 mainスレッド1回目の処理 MultiThreadスレッド2回目の処理 mainスレッド2回目の処理 MultiThreadスレッド3回目の処理 mainスレッド3回目の処理 MultiThreadスレッド4回目の処理 mainスレッド4回目の処理 MultiThreadスレッド5回目の処理 mainスレッド5回目の処理 MultiThreadスレッド6回目の処理 mainスレッド6回目の処理 MultiThreadスレッド7回目の処理 mainスレッド7回目の処理 MultiThreadスレッド8回目の処理 mainスレッド8回目の処理 MultiThreadスレッド9回目の処理 mainスレッド9回目の処理 MultiThreadスレッド10回目の処理 mainスレッド10回目の処理
Thread.sleepでプログラムを一時停止する方法
Thread.sleepを使うことで、プログラムのスレッドを一定時間停止する方法もあります。
記述方法は、以下の通りです。
Thread.sleep(停止させたい時間[ms]);
先ほどのサンプルコードを例に、スレッドを一定時間停止させながら処理を動かしてみましょう。
public class Main { public static void main(String[] args) { MultiThread mt = new MultiThread(); Thread thread = new Thread(mt); thread.start(); try { System.out.println("---MultiThreadスレッドの処理を待機---"); thread.join(); System.out.println("---MultiThreadスレッドの処理が終了---"); } catch(InterruptedException e) { e.printStackTrace(); } } } class MultiThread implements Runnable { public void run() { for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); System.out.println("MultiThreadスレッド" + (i + 1) + "回目の処理"); } catch(InterruptedException e) { e.printStackTrace(); } } } }
sleepメソッドを使う場合には、try-catch文で例外処理を記述する必要があります。
例外クラスには「InterruptedException」を記述しましょう。
例外処理については、以下の記事を参考してみるのをおすすめします。
【関連記事】
▶︎【Java】try-catch文の基本を解説!例外・エラー処理をマスターしよう【サンプルあり】
実行結果は先ほど紹介したものと同じになりますが、実行してみると一つのスレッドが処理されるごとに一時停止しているのがわかると思います。
Thread.interruptで別スレッドが終了するまで待機する方法
Thread.interruptを使うことで、別のスレッドに割り込みをかける方法もあります。
割り込みは、sleepメソッドやjoinメソッドの待ち状態時にかけることが可能です。
記述方法は、以下の通りです。
変数名.interrupt();
interruptメソッドの動きを確認するために、以下のプログラムを実行してみます。
public class Main { public static void main(String[] args) { MultiThread mt = new MultiThread(); Thread thread = new Thread(mt); thread.start(); try { System.out.println("mainスレッドの処理"); Thread.sleep(3000); System.out.println("3秒後に割り込み開始!"); thread.interrupt(); } catch(InterruptedException e) { e.printStackTrace(); } } } class MultiThread implements Runnable { public void run() { for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); System.out.println("MultiThreadスレッド" + (i + 1) + "回目の処理"); } catch(InterruptedException e) { System.out.println("割り込まれました!"); } } } }
実行結果
mainスレッドの処理 MultiThreadスレッド1回目の処理 MultiThreadスレッド2回目の処理 3秒後に割り込み開始! 割り込まれました! MultiThreadスレッド4回目の処理 MultiThreadスレッド5回目の処理
Thread.joinで別スレッドが終了するまで待機する方法
Thread.joinを使うことで、別のスレッドが終了するまで待機する方法もあります。
記述方法は、以下の通りです。
変数名.join();
joinメソッドの動きを確認するために、以下のプログラムを実行してみます。
public class Main { public static void main(String[] args) { MultiThread mt = new MultiThread(); Thread thread = new Thread(mt); thread.start(); for (int i = 0; i < 10; i++) { try { Thread.sleep(1000); System.out.println("mainスレッド" + (i + 1) + "回目の処理"); } catch(InterruptedException e) { e.printStackTrace(); } } } } class MultiThread implements Runnable { public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(1000); System.out.println("MultiThreadスレッド" + (i + 1) + "回目の処理"); } catch(InterruptedException e) { e.printStackTrace(); } } } }
実行結果
---MultiThreadスレッドの処理を待機--- MultiThreadスレッド1回目の処理 MultiThreadスレッド2回目の処理 MultiThreadスレッド3回目の処理 MultiThreadスレッド4回目の処理 MultiThreadスレッド5回目の処理 ---MultiThreadスレッドの処理が終了---
Threadクラスのその他のメソッドについては、以下のサイトから確認ができるので参考にどうぞ。
https://docs.oracle.com/javase/jp/7/api/java/lang/Thread.html
まとめ
Javaのスレッドの意味からスレッド・マルチスレッドの使い方、Threadクラスのメソッドについて解説しました。
マルチスレッドの概念や仕組みを理解することで、効率的な処理のプログラムができるので、ぜひこの記事を参考に実装してみてください。
ただし、sleepメソッドは誤差が発生するため、処理の順番が変わっていることもあるので注意しましょう。