脱!プログラミング入門

このブログではプログラミング入門後にさらに能力を伸ばすための援助ができるようにしたいです

Javaでマルチスレッドを使ってみる

 今回はJavaでマルチスレッドをどのように扱うのかについて説明していきたいと思います.マルチスレッドとは複数あるスレッドを同時に実行する技術のことを言います.マルチスレッドではない処理はプログラムに書かれた処理を上から下まで順番に1つのプロセスとして実行されます.一方マルチスレッドではある処理を1つのスレッドとして同時に複数のそのスレッドを実行します.こうすることで計算機のコストを消費しますが,処理速度はかなり速くなります.また,小規模な処理で少数のスレッド数の同時実行あれば計算機コストをあまり消費せずに効率的に処理を高速化できます.

マルチスレッドの使用方法

 Javaでマルチスレッドを使用する一例を次に示したいと思います.

class ThreadA extends Thread {
    private String threadName;

    public ThreadA(String tName) {
        this.threadName = tName;
    }

    @Override
    public void run() {
        try {
            System.out.println("Thread: " + this.threadName);
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class MultiThreadSample {
    public static void main(String[] args) {
        ThreadA t1 = new ThreadA("thread1");
        ThreadA t2 = new ThreadA("thread2");

        t1.start();
        t2.start();
    }
}

Javaでマルチスレッドを使用するにはまず,マルチスレッドを使おうとしているクラスでJavaの標準クラスであるThreadを継承します.そしてスレッドに分けたい処理をThreadクラスで定義されているrunメソッドをオーバーライドしてその中に書きます.

 スレッドを実行するにはThreadクラスを継承したクラスのインスタンスを生成して,Threadクラスで定義されているstartメソッドを実行することで実行できます.

 上の例ではThreadAクラスのインスタンスを2つ生成してそれぞれのインスタンスでstartメソッドを実行しています.実行すると以下のような結果になると思います.

$ java MultiMethodSample
Thread: thread1
Thread: thread2

注目すべきなのは実行の際の挙動です.2行の文字列が同時に画面に表示された後1秒経って実行が終了します.t1.start()が終了するのを待たずにt2.start()が実行されて,2つの処理が同時に実行されることがわかります.

for文のなかでスレッドを使う

 上記の方法では2つのスレッドしか集まっていませんでしたが,もっと多くのスレッドを同時に実行するにはfor文などの反復文のなかでスレッドのインスタンスを生成して実行することで可能となります.以下に例を示します.

import java.util.Random;

class ThreadB extends Thread {
    private String threadName;
    private int sleepTime;

    public ThreadB(String tName, int sTime) {
        this.threadName = tName;
        this.sleepTime = sTime;
    }

    @Override
    public void run() {
        try {
            System.out.println("Thread: " + this.threadName);
            sleep(this.sleepTime * 1000);
            System.out.println(this.threadName + " has finished!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class MultiThreadSample2 {
    public static void main(String[] args) {
        Random r = new Random();

        for (int i = 0; i < 10; i++) {
            int time = r.nextInt(7);
            ThreadB th = new ThreadB("thread" + i, time);
            th.start();
        }
    }
}

Threadクラスを継承したThreadBクラスのコンストラクタにスレッド名と乱数の整数を入れるようにしていて,runメソッド内で無作為な時間停止するようにしています.実行結果は以下のようになります.

$ java MultiThreadSample2
Thread: thread0
Thread: thread3
Thread: thread2
Thread: thread1
Thread: thread4
thread3 has finished!
Thread: thread5
thread1 has finished!
thread2 has finished!
...

10個のスレッドが同時に実行され,それぞれのスレッドのインスタンスが生成される際に格納された秒数経過した後「〇〇 has finished!」と表示されるようにしています.上記の例では同時に実行するスレッドの数の制限をしていませんが工夫次第でスレッド数を制限できるようになると思います.

終わりに

 今回はJavaでマルチスレッドを使用する方法について説明しました.プログラミングを始めたばかりの状態ではマルチスレッドを使用することはないと思いますが,処理の効率化などにかなり重要になってきます.まだある程度の大きさの規模のアプリケーションを作っていない場合は私もですが,どのような場面でマルチスレッドを使うのか想像できないというのがマルチスレッドの難しさだと思います.また,マルチスレッドのスレッド数が大きくなったり制御が複雑になったりするとどのような挙動でスレッドが処理されているのか非常に困難になります.

 何かと難しいマルチスレッドですが,色々なプログラムを書いていくなかで使って慣れていくしかなさそうです.このブログでもマルチスレッドを使ったプログラムを公開してどんな感じで使うのかを書いていけたらと思います.