【Java入門】マルチスレッド(Threadクラス)の使い方総まとめ

こんにちは!エンジニアの中沢です。

Javaにはマルチスレッドで処理を効率的に行うためのThreadクラスがあります。Threadクラスを使ってマルチスレッドの記述をすることで、複数の処理を並列に行う効率的な動作をさせることができます。この記事では、

スレッド(Thread)とは?
マルチスレッドの使い方を知りたい
sleepメソッドでスレッドを一定時間停止する方法を知りたい

という基本的な疑問から、

  • joinメソッドで別のスレッドの終了まで待機する方法
  • interruptメソッドで割り込む方法
  • synchronized修飾子でスレッドを同期する方法
  • ThreadLocalでスレッド毎に値を保持する方法

などの応用的な使い方に関しても解説していきます。今回はこれらの方法を覚えるために、Threadクラスのさまざまな使い方をわかりやすく解説します!

スレッド(Thread)とは

スレッドとは、プログラムの中のひとまとまりの処理の単位のことです。このスレッドが1列で順番に処理されていくことを、シングルスレッドと言います。

これに対して、スレッドが2列以上あり、複数の処理が並列に同時進行で処理されていくことをマルチスレッドと言います。

マルチスレッドの使い方

ここではマルチスレッドのプログラムを作成する方法を解説します。マルチスレッドのプログラムを作成するには、Threadクラスを継承したクラスを作る方法と、Runnableインターフェースを実装する方法とがあります。

サブクラスを使う方法

マルチスレッドのプログラムを作成するには、Threadクラスを継承したサブクラスを作り、そのクラスでrunメソッドをオーバーライドしてマルチスレッドの処理を記述します。

以下のように記述します。

Runnableインターフェースを実装する方法

マルチスレッドのプログラムを作成するもう一つの方法は、Runnableインターフェースを実装する方法です。Runnableインターフェースにはrunメソッドのみが定義されています。

以下のように記述します。

startメソッドで実行する方法

Threadクラスを継承したクラスを使う場合、そのインスタンス化する必要があります。また、Runnableインターフェースを実装したクラスを使う場合は、まず実装したクラスをインスタンス化したオブジェクトを作成し、そのオブジェクトでThreadクラスをインスタンス化する必要があります。

Threadクラスのオブジェクトからstartメソッドを呼び出すことでrunメソッドの処理がマルチスレッドで開始されます。startメソッドを使わずに、直接runメソッドを呼び出すとシングルスレッドで処理が実行されるので注意してください。

サブクラスを使って実行する場合

サブクラスを使ってマルチスレッドの処理をする方法を次のプログラムで確認してみましょう。

実行結果:

このプログラムではマルチスレッドの処理を行うために、Threadクラスを継承したMultiThredクラスを作成し、mainメソッドからstartメソッドでマルチスレッドの処理を実行しています。

また、マルチスレッドで処理が行われていることが分かりやすくなるように、sleepメソッドを使って処理を1秒停止しています。sleepメソッドについては次の章で詳しく解説します。実行結果から、2つのスレッドの処理が同時に行われていることが確認できます。

Runnableを実装したクラスで実行する場合

Runnableインターフェースを実装したクラスを使ってマルチスレッドの処理をする方法を次のプログラムで確認してみましょう。

実行結果:

このプログラムではマルチスレッドの処理を行うために、まずRunnableインターフェースを実装したMultiThredクラスを作成しています。実行するために、MultiThreadクラスのインスタンスを生成し、mtオブジェクトに格納しています。

このmtオブジェクトを使ってThreadクラスをインスタンス化し、オブジェクトthreadに格納しています。オブジェクトthreadからstartメソッドを呼び出して、マルチスレッドの処理を実行しています。

sleepメソッドでスレッドを一定時間停止する

ここではThreadクラスのsleepメソッドでスレッドを一定時間停止する方法を解説します。sleepメソッドは引数に停止させたい時間をミリ秒単位で指定して使用します。
(1000ミリ秒 = 1秒)

ただし、sleepメソッドは誤差が出るため高い精度が必要な場合には注意してください。また、sleepメソッドで待機中にinterruptメソッドで割り込みを行うと、InterruptedExceptionの例外が発生するので注意してください。

次のプログラムでsleepメソッドの使い方と誤差を確認してみましょう。

実行結果:

このプログラムの実行結果から、sleepメソッドで誤差が出ていることが確認できました。sleepメソッドでスレッドを一定時間停止する方法についてはこちらで詳しく解説しているので、ぜひ確認してください!

【Java入門】Threadをsleepメソッドで一定時間停止する方法
更新日 : 2019年4月8日

joinメソッドで別スレッドの終了まで待機

ここではjoinメソッドで別のスレッドが終了するまで待機する方法を解説します。joinメソッドは別のスレッドの処理が終了するまで待機したい場合に使用します。次のプログラムで確認してみましょう。

実行結果:

このプログラムでは、joinメソッドを使って別スレッドの処理が終わるまで待機しています。実行結果から、別スレッドの処理が終わってからメッセージを表示する処理をしていることが確認できます。

joinメソッドで別のスレッドの終了まで待機する方法についてはこちらで詳しく解説しているので、ぜひ確認してください!

【Java】joinメソッドでThreadが終了するまで待機する
更新日 : 2019年5月3日

interruptメソッドで割り込む

sleepメソッドやjoinメソッドの待ち状態の時に割り込みをかけるのがinterruptメソッドです。サンプルコードで確認しましょう。

実行結果:

このプログラムでは、mainメソッドがsleepメソッドで1000ミリ秒待ったあとに、別スレッドmtへ割り込みをかけています。

スレッドmtも同じ1000ミリ秒待ってから出力表示するようにしていますので、誤差によっては処理が実行できて出力表示している場合と割り込まれて例外処理を行っている場合がランダムに発生しています。

synchronized修飾子でスレッドの同期

synchronized修飾子が付いたメソッドをメンバに持つオブジェクトはそのメソッドを実行している間、同じオブジェクト内のsynchronized修飾子が付いたメソッドからアクセスされないようにロックされます。

また、メソッド同士を同時に実行させないように、あるメソッドは待機状態に、別のメソッドは実行可能状態にと区別する必要があります。waitメソッドを使って待機状態にして、notify、notifyAllメソッドを使って実行可能状態にします。

notifyAllメソッドはwaitにより待機状態にある全てのスレッドを実行可能状態にします。notifyメソッドは待機状態にあるスレッドのうち一つを実行可能状態にします。どのスレッドを実行可能状態にするか選択することはできません

それでは、synchronized修飾子を使ったスレッドの同期についてサンプルコードで確認しましょう。

実行結果:

このプログラムでは、2つの出力表示用のメソッドをそれぞれ別のスレッドから呼び出しています。1つ目のスレッドはこのメソッドを呼び出してからsleepメソッドを使って1000ミリ秒待機しています。もう一方のスレッドはメソッドを呼び出したあとに待機時間は設定していません。

2つのスレッドを実行した結果を確認すると、一方のスレッドは待機時間を設定してませんが、別のスレッドの待機が終了するまで実行せずに同期して待機していることがわかります。

ThreadLocalでスレッド毎に値を保持する方法

マルチスレッドでスレッド毎に値を保持するには、ThreadLocalクラスを使用します。ThreadLocalクラスを使用しない場合には、クラス変数の値が複数のスレッドで共有されるため、期待通りの動作にならない可能性があります。

ThreadLocalクラスでスレッド毎に値を保持する方法についてはこちらで詳しく解説しているので、ぜひ確認してください!

【納得Java】ThreadLocalでスレッド毎に値を保持する方法
更新日 : 2019年5月14日

まとめ

いかがでしたか?今回はスレッドの使い方について解説しました。マルチスレッドを使うと効率的な処理を行うプログラムができるのでぜひ覚えてくださいね。もし、スレッドを使う方法を忘れてしまったらこの記事を確認してください!

LINEで送る
Pocket

最短でエンジニアを目指すなら侍エンジニア塾

cta_under_bnr

侍エンジニア塾は業界で初めてマンツーマンレッスンを始めたプログラミングスクールです。これまでの指導実績は16,000名を超え、未経験から数多くのエンジニアを輩出しています。

あなたの目的に合わせてカリキュラムを作成し、現役エンジニア講師が専属であなたの学習をサポートするため効率よく学習を進めることができますよ。

無理な勧誘などは一切ありません。まずは無料体験レッスンを受講ください。

無料体験レッスンの詳細はこちら

書いた人

中沢 丈

中沢 丈

フリーランスエンジニア。
システム開発からコンテンツ作成まで幅広く対応します。

連絡先はこちらです。
[email protected]

おすすめコンテンツ

あなたにぴったりなプログラミング学習プランを無料で診断!

プログラミング学習の効率を劇的に上げる学習メソッドを解説