【Java】Threadクラスによるマルチスレッドの実現

2018年3月11日

本稿はマルチスレッドを利用する方法について説明します。

マルチスレッドとは、複数の単位で処理を実行することです。

マルチスレッドを利用することで、アプリケーションのパフォーマンスが向上する例もあります。

今まではmainクラスから順番に処理を実行していきましたが、この処理を実行していく単位をスレッドといいます。

今回はそのスレッドを複数起動させ、同時実行していく方法を説明します。

最も一般的なスレッドの起動方法

最も一般的なスレッドの起動はRunnableインターフェースとThreadクラスを利用した方法になります。

まず、Runnableインターフェースについてですが、スレッドが起動したときに一番最初に実行されるrunメソッドを実装するためのJava標準インターフェースです。

スレッド関連の処理を組む場合は大抵Runnableインターフェースを実装して、プログラミングします。

Runnableインターフェースは引数なしのrunメソッドを実装するだけで完了です。

次に、Threadクラスですが、こちらもJava標準クラスであり、スレッドを起動することができます。

起動には、Threadクラスをインスタンス化し、コンストラクタにRunnableインターフェースを実装したインスタンスを指定します。

後は、Threadインスタンスのstartメソッドを実行してスレッドを起動します。

それではサンプルをご覧ください。

public class Test{
	public static void main(String[] args){
		ThreadTest test = new ThreadTest();
		Thread th = new Thread(test);
		th.start();
		System.out.println("スレッドを起動しました。");
	}
}
class ThreadTest implements Runnable{
	public void run(){
		System.out.println("スレッドテスト");
	}
}
実行結果

スレッドを起動しました。
スレッドテスト

この例では、メインメソッドから実行される、メインスレッドと、runメソッドから実行されるサブスレッドの二つが処理を実行していき、画面表示しています。

※処理単位が分割されているため、結果の表示順が入れ替わる可能性があります。

複数スレッドが立ちあがった場合は、すべての処理が終了するまでプログラムは終了しません。

こちらは、二つのスレッドを実行した時のイメージです。

Threadクラスの継承で実装する

スレッドクラスを継承することで、スレッド起動をもう少しだけ、楽に実装することもできます。

次はサブスレッドを二つ立ち上げ、合計3スレッドを実行する例を見てみましょう。

public class Test{
	public static void main(String[] args){
		BoyChara boy = new BoyChara();
		GirlChara girl = new GirlChara();
		boy.start();
		girl.start();
		System.out.println("スレッドを起動しました。");
	}
}
class BoyChara extends Thread{
	public void run(){
		System.out.println("少年は歩きました。");
	}
}
class GirlChara extends Thread{
	public void run(){
		System.out.println("少女は歩きました。");
	}
}
実行結果

スレッドを起動しました。
少女は歩きました。
少年は歩きました。

スレッドが3つになったときのイメージです。

スレッドの使いどころと注意点

スレッドを増やすとメインの処理を実行しながら、別の処理を実行することができるため、便利ですが、複数の処理単位を把握しながらプログラムを組まなければならないので、難易度が上がります。

マルチスレッドを扱う上で難易度が高いのがスレッド間の同期をとることです。

想定外の場面でデータが書き換わる可能性が増すため、不用意にスレッドを起動しすぎないようにしましょう。

マルチスレッドの使いどころによってはパフォーマンスが良くなりますが、むやみやたらに使用するのでは逆に非効率となる可能性があります。

スレッドの使いどころですが、処理待ちや重い処理が実行される時に、別の処理をしたい時が考えられます。

例えば、通信の応答待ちで処理が進まなくなるのを防ぐために、スレッドを起動したり、時間のかかる画像読み込み処理中に「NOW LOADING」と画面に表示したい場合に使用できそうです。

私がゲーム制作する時は、キー処理、描画処理などを行うメインスレッド、ゲームの処理、再描画命令を行う処理スレッド、BGM再生用スレッドの3つしか使用しません。

通信の要素が加わると、もっと増えそうですが、オフラインゲーム制作においては、2,3スレッドが使用できれば問題ないでしょう。

Java

Posted by nompor