Javaアプリケーションでスレッドを使う

広告

ではまずJavaのアプリケーションでスレッドを使ったサンプルを試してみましょう。マルチスレッドを使う場合には、メインで動いていてその中で別のスレッドを作成などを行うクラスと、別に作成されたスレッドによって実行されるクラスの2つのクラスを考える必要があります。

本来動いているスレッドとは別に新しいスレッドを作成してプログラムを実行させる場合、その新しいスレッドによって実行されるクラスがスレッドに対応している必要があります。スレッドに対応させるにはそのクラスをThreadクラスのサブクラスとして作成します。

class SubThread extends Thread{

  // ...

}

Threadクラスそのものは、スレッドを新たに1つ作成するためのものです。Threadクラスのサブクラスとしてクラスを作成し、そのクラスのオブジェクトを作成することで、スレッドを1つ作成してそのスレッド上で動くオブジェクトを作成することが出来ます。

Threadクラスを見ておきましょう。

  • java.lang.Object
  • java.lang.Thread
  • public class Thread extends Object implements Runnable

ThreadクラスはRunnableインターフェースを実装したクラスです。メインのスレッド以外に別のスレッドとして動作させるクラスはこのRunnableインターフェースを実装する必要があります。ThreadクラスはRunnableインターフェースを実装したクラスですので、結果的にThreadクラスのサブクラスはRunnableインターフェースを実装したことになりますのでスレッドとして動作させることができるわけです。

Runnableインターフェースを実装するクラスはrunメソッドを実装する必要があります。これは新しくスレッドが作成され、そのスレッドの中でクラスが実行を開始される時に呼び出されるメソッドです。(Javaアプリケーションにおけるmainメソッドのようなものです)。

ThreadクラスはRunnableインターフェースを実装したクラスですので、当然runメソッドを持っています。ですが、Threadクラスでは必要最小限の処理しかこのメソッド内で行っていませんので、Threadクラスを継承したサブクラスを作成し、そのクラスに何か処理を行わせる場合には、自分でrunメソッドを書き換えてそのクラスで行って欲しい処理を記述しておく必要があります。つまり下記のような感じとなります。

class SubThread extends Thread{
  public void run(){
    // ここからプログラムがスタート
  }
}

これで別のスレッドを使って実行されるクラスが出来ました。

スレッド対応のクラスを呼び出す側の記述

スレッド対応のクラスを作成したら、今度はメインの方のプログラム側の方を見ていきます。簡単な例で考えてみます。

class MainThread{
  public static void main(String args[]){
    SubThread sub = new SubThread();
  }
}

class SubThread extends Thread{
  public void run(){
  }
}

Javaアプリケーションとしてコマンドラインから実行されるMainThreadクラスの中で、スレッド対応したクラスのオブジェクトを1つ作成しています。そして新しいスレッドとして別の動作をさせたい場合には、Threadクラスで定義されているstartメソッドを使ってスレッドの開始を指示することでスレッドを開始します。

このスレッドの実行を開始します。Java 仮想マシンは、このスレッドの run 
メソッドを呼び出します。

その結果、(start メソッドへの呼び出しから復帰する) 現在のスレッドと(その
run メソッドを実行する) 別のスレッドという 2 つのスレッドが並列に実行さ
れます。

スレッドを複数回起動するのは、決して正しいとは言えません。特に、スレッド
は実行を終えてから再起動することはできません。

例外:
  IllegalThreadStateException - スレッドがすでに起動していた場合

このメソッドを呼び出すことでrunメソッドが内部的に呼ばれ、スレッド対応クラスの方のプログラムが開始されます。startメソッドはThreadクラスで定義されていますので、サブクラスの方で別途定義する必要はありません。

class MainThread{
  public static void main(String args[]){
    SubThread sub = new SubThread();
    sub.start();

    // メイン側の残りのプログラム処理を記述
  }
}

class SubThread extends Thread{
  public void run(){
    // サブ側で実行するプログラム処理を記述
  }
}

メイン側とサブ側は別のスレッドで実行されますので、お互いの状況に関係無く決められた事をそれぞれ処理していきます。

サンプルプログラム

一度簡単なサンプルで動作を確認してみましょう。下記ではメイン側が巨人の応援、サブ側が阪神の応援をする処理を行わせています。

ThreadTest1.java

public class ThreadTest1{
  public static void main(String args[]){
    SubThread sub = new SubThread();
    sub.start();

    /* メイン側で行う処理 */
    for (int i = 0 ; i < 10 ; i++){
      System.out.println("巨人がんばれ!!");

      /* 少し待機する */
      try{
        Thread.sleep(300);
      }catch(InterruptedException e){
      }
    }
  }
}

class SubThread extends Thread{
  public void run(){
    /* サブ側で行う処理 */
    for (int i = 0 ; i < 10 ; i++){
      System.out.println("阪神負けるな!?");

      /* 少し待機する */
      try{
        Thread.sleep(500);
      }catch(InterruptedException e){
      }
    }
  }
}

上記を実際に実行してみると下記のようになります。

スレッドのテスト

上記ではあまり軽い処理だとスレッドが平行して動いていることが分かりにくいので、標準出力に文字を出力したら少し待機するようにしています。

見て頂くと分かる通り、メイン側とサブ側で、それぞれ別々にプログラムの処理を進めていきます。このように別のスレッドを動かすことで複数の処理を(擬似的ではありますが)同時に動かす事ができるようになります。

( Written by Tatsuo Ikura )