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

image (4)
中沢 丈
書いた人 中沢 丈
侍エンジニア塾ブログは、未経験からWebアプリ開発と仕事獲得をサポートする
侍エンジニア塾のオウンドメディアです。
プログラミング学習を覗き見

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

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メソッドでスレッドを一定時間停止する方法についてはこちらで詳しく解説しているので、ぜひ確認してください!

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

ここではjoinメソッドで別のスレッドが終了するまで待機する方法を解説します。

joinメソッドは別のスレッドの処理が終了するまで待機したい場合に使用します。

次のプログラムで確認してみましょう。

実行結果:

このプログラムでは、joinメソッドを使って別スレッドの処理が終わるまで待機しています。

実行結果から、別スレッドの処理が終わってからメッセージを表示する処理をしていることが確認できます。

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

interruptメソッドで割り込む

sleepメソッドやjoinメソッドの待ち状態の時に割り込みをかけるのがinterruptメソッドです。

サンプルコードで確認しましょう。

実行結果:

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

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

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

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

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

waitメソッドを使って待機状態にして、notifynotifyAllメソッドを使って実行可能状態にします。

notifyAllメソッドはwaitにより待機状態にある全てのスレッドを実行可能状態にします

notifyメソッドは待機状態にあるスレッドのうち一つを実行可能状態にします

どのスレッドを実行可能状態にするか選択することはできません

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

実行結果:

このプログラムでは、2つの出力表示用のメソッドをそれぞれ別のスレッドから呼び出しています。

1つ目のスレッドはこのメソッドを呼び出してからsleepメソッドを使って1000ミリ秒待機しています。

もう一方のスレッドはメソッドを呼び出したあとに待機時間は設定していません。

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

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

マルチスレッドでスレッド毎に値を保持するには、ThreadLocalクラスを使用します。

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

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

まとめ

いかがでしたか?

今回はスレッドの使い方について解説しました。

マルチスレッドを使うと効率的な処理を行うプログラムができるのでぜひ覚えてくださいね。

もし、スレッドを使う方法を忘れてしまったらこの記事を確認してください!

Javaカリキュラム無料公開中!
この記事はJava入門完全攻略ガイド【基礎学習/アプリ開発/仕事獲得】の一部になります。このカリキュラムは、プログラミング入門者が、基礎学習からアプリ開発、さらには仕事獲得まで体系的に学べる内容となっています。

Java学習に必要な情報を一つにまとめていますので効率よくJavaを学ぶことが出来ます。この機会に是非活用していただければと思います。


33歳、未経験だった僕がフリーエンジニアになれた理由
現在フリーでWEBエンジニアをやられている濱口直行さん。33歳で、プログラミングを学び始め、約半年という短い期間で独立までされた学習ログを余すことなくインタビューさせていただきました。

プログラミングを学習中の方はもちろん、独立をお考えの方まで幅広く活用できる記事になっています。この機会に是非活用していただければと思います。


最短でJavaを習得したい方へ

もし、あなたが、

「難しすぎて学習が全然進まない」
「学習量が膨大でゴールが見えない」
「エラーを解決するのに何日もかかってしまう」

など、プログラミング学習やキャリアに関してお困りであれば、まずは『無料体験レッスン』にお申し込み下さい。

あなたにとって、最適の解決策をご提案させていただきます。

詳しくは下の画像から詳しいサービス内容をご確認ください。

cta_bannar-java2

学習者インタビュー

人気講師インタビュー

人気記事セレクション

プログラミング学習者必見

専属講師に質問し放題、レッスンし放題!最短1ヶ月でフリーランスエンジニア
プログラミング学習カリキュラム無料公開中
Ruby学習カリキュラム無料公開中
Python学習カリキュラム無料公開中
 1記事最大11,000円!テックライター募集


LINEで送る
Pocket

この記事が気に入ったら
いいね!をしてフォローしよう

最新情報をお届けします

書いた人

中沢 丈

中沢 丈

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

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