並行プログラミング


並行プログラミングの目的

並行プログラミングの目的は二種類ある.一つは並列計算機の上で高速に計 算をするためのものである.もう一つは,逐次計算機上で動かすことを想定し ているが,自然に書くためである.Java における並列プログラミングは主に 後者を目的としている.

Java言語ではスレッド(thread, 「thread of control」(制御の糸)の短縮形) と呼ばれる自立的に動く単位を実行主体として並列性を制御する.論理的に並 列というのは,本当に並列に動くのではなく,一つの計算機上で時分割 (time-sharing)に動くことも許す(というより,大多数の実装ではそうなってい る)ことを意味する.スーパーコンピュータ用の FORTRAN処理系などでは,for ループを書くと自動的に並列化するものもあるが,Javaはこれらと違って明示 的な(explicitな)並列実行の指定をおこなっていて,スレッドを生成したとこ ろでのみ並列性が現われる.

Unix上のC言語でもプロセス(あるいはOSのスレッド)を生成して,並行プログ ラムを書くことができるが,Java言語ではライブラリではなく言語の中核部分 に並行プログラムを支援するための仕組みを入れているので,書きやすいし, OSに依存しない書き方ができる.

論理的に並列に書くと自然に書けるプログラムは次のようなものである.


新しいスレッドを取得する方法

Javaでは新しい制御のスレッドを手に入れる方法が2つある.

Threadクラスにはrun メソッド以外に,スレッドの実行を制御するための startメソッドがある.また,Threadクラスの静的メソッドとしてsleep(ミリ秒 単位での休止) もあり,よく使われる.

両方の方法で,スレッドを作るプログラムのサンプルを見てみよう.

// 2つのスレッドを作るクラス ThreadSample
public class ThreadSample {
  public static void main(String [] args){
  // Threadのサブクラス ExtnfThreadのインスタンスt1の作成
    ExtnOfThread t1 = new ExtnOfThread();
    // スレッド t1 の実行開始
    t1.start();

    // Runnableを実装(implement)したクラスのインスタンスを元に
    // Thread クラスのインスタンス t2 を作る
    Thread t2=new Thread(new ImplOfRunnable());
    // スレッド t2 の実行開始
    t2.start();
  }
}
// ThreadのサブクラスExtnOfThreadの宣言
class ExtnOfThread extends Thread{
// Threadをstartすると,このrunが呼ばれる
  public void run(){
    System.out.println("Extension of Thread running");
    // 1000ミリ秒 (=1秒)の間,スリープ(実行中断)
    // その間に別の割り込み(interrupt)に割り込まれた時は終了する
    try{sleep(1000);}
    catch(InterruptedException ie){return;}
    System.out.println("Extension of Thread exiting");
  }
}

class ImplOfRunnable implements Runnable{
  public void run(){
    System.out.println("Implementation of Runnable running");
    // このオブジェクトを実行しているスレッドをThread.currentThread()で得る
    // ことができる
    try{Thread.sleep(1000);}
    catch(InterruptedException ie){return;}
    System.out.println("Implementation of Runnable exiting");
  }
}
実行結果は以下のようになるだろう.
Extension of Thread running
Implementation of Runnable running
Extension of Thread exiting
Implementation of Runnable exiting
スレッドを呼び出す側は,Thread オブジェクトを作って,そのメソッド startを呼び出す.メソッド start はスレッドが動き出すための準備をした後 で,run を呼び出す.これが,スレッドの実行の主体となる.runメソッドの 実行を終えると,スレッドの実行も終わる. この講義ではスレッドを作る方法としては3,主にRunnableインタフェースの実装で扱う.
Threadは並行(concurrent) に実行されると言っても,多くの場合は時分割 (time-sharing)で一度には1つのThreadしか動いていない.しかし,「複数の プロセッサを載せたマシンで」,「Java処理系が複数プロセッサを使えるよう になっている(green_threadsではなくnative_threadsを使用)」場合は,実際 に複数のプロセッサ上で同時に動くこともある.センターのUnixサーバ(4プロ セッサマシン)でJava SDK 1.4 を使っている場合は,この場合に該当する.

次に進む