Runnableインターフェース

広告

前のページではスレッドとして動かすクラスをThreadクラスのサブクラスとして作成しました。ただJavaのクラスは1つのクラスの子クラスにしかなれない制約があるため、例えば既に他のクラスのサブクラスになっているもの(アプレットもAppletクラスのサブクラスとして作成します)は、さらにThreadクラスのサブクラスにすることは出来ません。

ではどうするかと言いますと、前のページでは別スレッドして動かしたいクラスをThreadクラスのサブクラスとすることで、スレッドを新たに作成しつつ、そのスレッド上で動くオブジェクトを作成できるようにしたわけですが、スレッドはスレッドとして1つ作成して、そのスレッド上で動くクラスを指定するという方法に変更します。

スレッドを1つ作成するには、Threadクラスそのもののオブジェクトを1つ作成します。

新しい Thread オブジェクトを割り当てます。このコンストラクタは、
Thread(null, target, gname) と同じ効果を持ちます。この場合、gname は、新
しく作成される名前です。自動的に作成される名前は、n を整数とすると 
"Thread-"+n の形式を取ります。 

パラメータ:
  target - その run メソッドが呼び出されるオブジェクト

これはThreadクラスのコンストラクタの1つですが、スレッドが作成され、そのスレッドが開始された時に実行されるクラスを引数に指定します。そしてこのスレッドがstartメソッドによって開始されると、引数に指定したクラスのrunメソッドが内部的に呼び出されるという仕組みです。

例えば下記のような使い方となります。

class MainThread{
  public static void main(String args[]){
    /* 別スレッドとして動作させるオブジェクトを作成 */
    SubThread sub = new SubThread();

    /* 別のスレッドを作成し、スレッドを開始する */
    Thread thread = new Thread(sub)
    thread.start();
  }
}

class SubThread{
  public void run(){
  }
}

ただし、上記の記述は間違いです。Threadのコンストラクタの引数に指定できるクラスは、スレッドとして動作できるクラスでなければならず、Runnableインターフェースを実装したクラスでなければなりません。よって、正確には下記のようになります。

class MainThread{
  public static void main(String args[]){
    /* 別スレッドとして動作させるオブジェクトを作成 */
    SubThread sub = new SubThread();

    /* 別のスレッドを作成し、スレッドを開始する */
    Thread thread = new Thread(sub)
    thread.start();
  }
}

class SubThread implements Runnable{
  public void run(){
  }
}

Runnableインターフェースで実装しなければいけないメソッドはrunメソッドだけなので、上記で問題無く動作する事が出来ます。(そもそも、スレッドが開始された時に対象のクラスのrunメソッドが呼ばれるのは、そのクラスがRunnableインターフェースを実装し、そのインターフェースで定義されたrunメソッドが呼ばれると決まっているからです)。

サンプルプログラム

では前のページで作成したサンプルをRunnableインターフェースを実装したクラスに変更して試してみましょう。

ThreadTest2.java

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

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

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

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

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

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

Runnableのテスト

結果は前のページの場合と、同じになります。

Threadクラスのサブクラスとする変わりにRunnableインタフェースを実装した形にすることのメリットは、他のクラスのサブクラスであってもインターフェースの実装は自由なことです。その為、アプレットなどのような既に他のクラスのサブクラスであってもRunnableインターフェースを実装することは可能です。

( Written by Tatsuo Ikura )