【Java】マルチスレッドの実装方法

# はじめに
今回はJavaのマルチスレッドの実装方法について解説します。
マルチスレッドは複数の処理を並行して行いたい場合に使用します。

また、マルチスレッドはThreadというクラスを使用するのですが、
Threadクラスでよく使用するメソッドを紹介したいと思います。

以降、以下のバージョン、環境での解説となります。

IDE：eclipse
Javaバージョン：8
OS:Mac OS

それでは、早速解説していきます。

# 1. フォルダ構成
今回作成するサンプルソースのフォルダ構成は以下の通りです。

<img width="280" alt="スクリーンショット 2018-11-12 20.57.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/298750/2d289993-e274-cccd-be93-089b2bedbca9.png">

# 2. マルチスレッド処理の実装
## 2-1. サンプルプログラム概要
今回サンプルで実装する内容ですが、メインクラスである「Main.java」を起動し、サブクラスである「SubThreadA.java」と「SubThreadB.java」を並列でスタートさせるという基本的なプログラムを実装します。

## 2-2. サブクラスの実装
まずは今回並列で処理させたいサブクラスの実装を行います。

マルチスレッドのプログラムを作成するには、Threadクラスを継承し、そのクラスでrunメソッドを記述します。
以下のように記述します。

```
class サブクラス名 extends Thread {
    public void run() {
        処理
    }
}
```

今回のサンプルプログラムでは、それぞれのスレッドで以下のような文言がコンソールに出力されるようなプログラムを実装していきましょう。

SubThreadA.java → 「スレッドAを開始しました。」
SubThreadB.java → 「スレッドBを開始しました。」

```SubThreadA.java
package main;

public class SubThreadA extends Thread {
    public void run() {
        System.out.println("スレッドAを開始しました。");
    }
}
```

```SubThreadB.java
package main;

public class SubThreadB extends Thread {
    public void run() {
        System.out.println("スレッドBを開始しました。");
    }
}
```

## 2-3. メインクラスの実装
次に先ほど作成したスレッドを起動させる処理をメインクラスへ実装します。

実装方法ですが、先ほど作成したサブクラスのオブジェクトからstartメソッドを呼び出すことでrunメソッドの処理がマルチスレッドで開始されます。

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

```
    public static void main(String[] args) {
        サブクラス名 mt = new サブクラス名();
        mt.start();
}
```
それでは、先ほどの「SubThreadA」と「SubThreadB」を呼び出す処理を記述していきましょう。

```main.java
package main;

public class Main {
    public static void main(String[] args) {
        // Threadクラスを継承したサブクラスのオブジェクト作成
        SubThreadA mt1 = new SubThreadA();
        SubThreadB mt2 = new SubThreadB();

        // サブクラスの実行
        mt1.start();
        mt2.start();
    }
}
```

上記記述完了しましたら、Main.javaを右クリック>Javaアプリケーションの実行で実行してみましょう。
コンソール画面に以下の文言が出力されていればOKです。

```コンソール
スレッドAを開始しました。
スレッドBを開始しました。
```

# 3. sleepメソッドの実装
ここではThreadクラスのsleepメソッドでスレッドを一定時間停止する方法を解説します。

sleepメソッドは引数に停止させたい時間をミリ秒単位で指定して使用します。
(1000ミリ秒 = 1秒)

また、sleepメソッドでは、割り込み等でInterruptedExceptionの例外が発生する可能性があるのでtry-catch文で囲み例外処理をする必要があります。

それでは今回は、「SubThreadA」を3秒遅らせて実行してみましょう。

```SubThreadA.java
package main;

public class SubThreadA extends Thread {
    public void run() {
        try {
        // 3秒スリープ
        Thread.sleep(3000);
        System.out.println("スレッドAを開始しました。");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
```
Main.javaを右クリック>Javaアプリケーションの実行で実行してみましょう。
スレッドBの3秒後にスレッドAが開始され、コンソール画面に以下の順番で文言が出力されていればOKです。

```コンソール
スレッドBを開始しました。
スレッドAを開始しました。
```

# 4. joinメソッドの実装
joinメソッドは別のスレッドの処理が終了するまで待機したい場合に使用します。
終了するかどうか監視したいスレッドのオブジェクト.join()とコーディングします。

また、sleepメソッドと同様に、割り込み等でInterruptedExceptionの例外が発生する可能性があるのでtry-catch文で囲み例外処理をする必要があります。

それでは、「SubThreadA」の処理が終了してから「SubThreadB」の処理を行うようにしてみましょう。

```Main.java
package main;

public class Main {
    public static void main(String[] args) {
        try {
            SubThreadA mt1 = new SubThreadA();
            SubThreadB mt2 = new SubThreadB();

            mt1.start();
            mt1.join();  //SubThreadAが終了するまで待機
            mt2.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
```

Main.javaを右クリック>Javaアプリケーションの実行で実行してみましょう。
少し時間が経ってから、スレッドA→Bの順で実行され、コンソール画面に以下の文言が出力されていればOKです。

```コンソール
スレッドAを開始しました。
スレッドBを開始しました。
```

# さいごに
2020年から個人ブログはじめました！

フリーランスエンジニアになって得た知識と経験をもとに、フリーランスエンジニアに関する情報をはじめ、IT技術情報や業界情報、エンジニアライフハック等のコンテンツを配信していく予定です。

まだまだ記事数は少ないのですが、週単位で更新してますので、もしご興味ございましたら、みていただけると嬉しいです。

https://yacchi-engineer.com/