Javaでマルチスレッドプログラミング -スレッドの概要と実行-

Javaでマルチスレッドプログラミングを覚えようと、こちらのサイトを読んで写経してみた。
 

マルチスレッドとは

Javaはマルチスレッドを取り扱うことのできる言語である。マルチスレッドとは複数のスレッドという意味である。
スレッド(Thread)とは、「糸」を意味する単語で、Javaのプログラムを実行している主体である。プログラムが実行されると、Java仮想マシンは新しいスレッドを作成し、そのスレッドによって指定したクラスのmainメソッドが実行される。スレッドはmainメソッドを最初から順番に命令を実行していき、mainメソッドの実行が終了すると消滅する。
マルチスレッドでは、例えば、1つのプログラムの中で、通信処理を行いながら、同時に計算処理を行うことなどができる。
 

時分割処理

CPUを1つしか持たないコンピュータでは、厳密には1つの処理しか同時には実行することができない。そこで、「マルチスレッド」では、通常「時分割処理」という方法が用いられている。「時分割処理」とは、短い時間間隔で実行する処理を切り替える方法である。複数の処理を頻繁に切り替えて実行することで、仮想的に複数の処理を同時に実行しているように見せかけることが出来る。
 

排他制御と同期

複数のスレッドがそれぞれまったく関係ない処理をしているときは、特にそれらのスレッド間の関係を意識する必要はない。しかし、複数のスレッドが同じオブジェクトを操作したり、協調して処理を行う場合には、スレッド間の相互作用に注意しなければならない。
ある処理を、他のスレッドに邪魔されないようにあるスレッドだけで独占して実行することを「排他制御」と言う。また、複数のスレッド間で待ち合わせしたり、処理のタイミングを合わせることを「同期」と言う。Javaでは排他制御や同期を行うためのさまざまな方法が用意されている。
 

スレッドのライフサイクル

Javaのスレッドは、作成されてから消滅するまでにいくつかの状態を遷移する。状態の遷移を図に表すと、次のようになる。
 
※図はこちらのサイトから引用させていただいた。
ThreadLifeCycle
 

初期状態

新しいスレッドを作成した状態。この状態ではまだスレッドは動作していない。次の章で説明するstartメソッドにより、実行可能状態となる。
 

実行可能状態

スレッドが動作している状態。この状態は、さらに「実行中」と「実行準備完了」の2つの状態に分けられる。「実行中」は、時分割処理によって実際にCPUによって処理が実行されている状態である。
 
CPUが1つしかないコンピュータでは、「実行中」のスレッドは同時には最大で1つだけしか存在しない。その他のスレッドは「実行準備完了」状態で、CPU時間が割り当てられるのを待機している。
 

ブロック状態

ディスクの入出力操作や、スレッドの排他制御や同期処理などにより、スレッドの動作が一時的に休止している状態。ブロック状態となっている原因が解消されれば「実行可能状態」に戻る。スレッドは、動作中に何度も「実行可能状態」と「ブロック状態」を行き来することができる。
 

終了状態

スレッドの処理が終了した状態。一度終了状態になったスレッドは、再び動作を開始することはない。
 

スレッドの実行

プログラムの中でスレッドを作成する方法は2つある。ひとつはjava.lang.Threadクラスを継承(extends)したクラスを作成する方法である。もうひとつはjava.lang.Runnableインタフェースを実装(implements)したクラスを作成する方法である。以下では、それぞれの方法について説明する。
 

Threadクラスを継承する方法

Threadクラスを継承したクラスを利用して新しいスレッドを実行するには、次のような手順を用いる。

  • Threadクラスを継承するクラスを作成する。
  • そのクラスでrunメソッドを宣言する。
  • そのクラスのインスタンスを作成する。
  • そのインスタンスのstartメソッドを呼び出す。

 

class CountDownThread extends Thread {
    private String name;

    public CountDownThread(String name) {
        this.name = name;
    }

    public void run() {
        for (int i = 3; i >= 0 ; i--) {
            try {
                sleep(1000);
            } catch (InterruptedException e) {}
            System.out.println(name + " : " + i);
        }
    }

    public static void main(String[] args) {
        CountDownThread t1 = new CountDownThread("thread 1");
        CountDownThread t2 = new CountDownThread("thread 2");
        t1.start();
        t2.start();
    }
}

 
Threadクラスを継承したCountDownThreadクラスである。mainメソッドからCountDownThreadクラスのインスタンスを作成し、Threadクラスのstaticメソッドであるstartメソッドを呼び出している。ここで、runメソッドではなく、startメソッドを呼んでいることに注意してほしい。runメソッドを呼んでもrunメソッドに記述した処理は実行されるが、通常のメソッド呼び出しと同じで、新しいスレッドは起動されない。startメソッドを呼ぶことによって、新しいスレッドが起動され、その新しいスレッドによってrunメソッドが実行される。
 

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

Runnableインターフェースを実装したクラスを利用して新しいスレッドを実行するには、次のような手順を用いる。
 

Article written by

コメントを残す