Java Thread

Menu Menu

Java の軽量プロセス(スレッド)について調べる。


軽量プロセスと手続きの比較

Class processExample.ThreadCreate は、簡単なスレッドの作成の例である。

    package processExample;
    public class ThreadCreate extends Thread {
	    SimpleThread t1;
	    SimpleThread t2;
	    SimpleThread t3;
	    
	    static public void main(String [] args) throws InterruptedException {
		    SimpleThread t1 = new SimpleThread("t1",2,1,2,3);
		    SimpleThread t2 = new SimpleThread("t2",2,4,5,6);
		    SimpleThread t3 = new SimpleThread("t3",2,7,8,9);
		    
		    t1.start();
		    t2.start();
		    t3.start();
	    }
    }

Java では、Thread Class を継承する、あるいは、Interface Runnable を実装することによって、スレッドを実現する。Thread Class は、Interface Runnable を実装している。それは、つまり、public void run();というメソッドを持っているということである。それをoverrideすることにより、スレッドの動作を定義する。

Class processExample.SimpleThread

    package processExample;
    public class SimpleThread extends Thread {
	    String name;
	    int count;
	    int a;
	    int b;
	    int c;
	    public SimpleThread(String _name,int count_,int a_,int b_,int c_) {
		    String msg;
		    name = _name; a = a_; b = b_; c = c_;
		    count = count_;
		    msg = "Thread "+name+" created.";
		    System.out.println(msg);
	    }
	    
	    public void run() {
		    while(count < 0 || count-- > 0) {
			    String msg = "Thread "+name+" "
				+Integer.toString(a)+" "+Integer.toString(b)
				+" "+Integer.toString(c);
			    System.out.println(msg);
		    }
	    }
    }

この段階では、Thread の実行は、通常のメソッド呼び出しと変わらないように見える。


プロセスのコンテキスト切り替えの観察

一つのスレッドは一つの仮想CPU(プログラムカウンタと、実行環境)を持っていて、途中で、別なスレッドに自発的、あるいは、自動的に切り替わる。 Threadの yield() メソッドを使って、自発的に切替えることが可能である。

上の例題のSimpleThread のrun() メソッドの中の適当な場所に yield()を挿入して、実行が切り替わる様子を観察せよ。この結果より、2 つの軽量プロセスが交互に動作していることがわかる。

yield() は、現在実行中の軽量プロセスが、利用しているCPU 資源を自発的に他の軽量プロセスに譲る命令である。yield()を呼び出した結果、現在実行中の軽量プロセスは、実行可能状態となる。制御はスケジューラに移る。スケジューラは、CPU資源の待ち行列から、実行可能状態の軽量プロセスを選び、その軽量プロセスに制御を移す。


スレッドを止める方法

この例では、スレッドは決まった回数の動作を行うと自発的に止まる。これを外から止めるにはどうすれば良いだろうか? それには、stop()というメソッドが用意されている。

Class processExample.ThreadStop

    package processExample;
    public class ThreadStop extends Thread {
	    public boolean start;
	    SimpleThread t1;
	    SimpleThread t2;
	    SimpleThread t3;
	    
	    static public void main(String [] args) throws InterruptedException {
		    ThreadStop self = new ThreadStop();
		    self.start = true;
		    self.start();
		    self.init();
		    self.sync();
	    }
	    
	    public void init() throws InterruptedException {
		    t1 = new SimpleThread("t1",-1,1,2,3);
		    t2 = new SimpleThread("t2",-1,4,5,6);
		    t3 = new SimpleThread("t3",-1,7,8,9);
		    
		    t1.start();
		    t2.start();
		    t3.start();
	    }
	    
	    public synchronized void sync() throws InterruptedException {
		    wait(120);
		    t1.stop();
		    t2.stop();
		    t3.stop();
	    }
    }

SimpleThread は、count に-1を指定されると無限ループするように作られている。これを実際に実行してみて、スレッドが止まる様子を観察せよ。それぞれのSimpleThread のwhile loopは何回実行されているだろうか? (log を取り、grep と wc で調べることが出来る。あるいは、プログラムを変更して、回数をカウントすることもできる)

wait(int) は、指定された秒数を待つメソッドである。これは、Object のメソッドであり、Thread のメソッドではない。wait() を呼ぶ時には、必ず、synchronized なメソッドから呼ぶ必要がある。synchronized keyword と取り除いて、どのようなエラーがコンパイル時、あるいは、実行時に出るかを調べよ。

ここでは、ThreadStop は、self というインスタンス(instance)を一旦作成している。これは、wait() 使う、このプログラムでは必須である。この理由を、static method と static でないmethod の違いから説明せよ。(static class を使用して、この問題を避けることもできるらしい...)

Thread API 定義によると、stop() は、

    Deprecated.

とある。これは、どういう意味か?
     Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?

という文書の指示に従って、stop() を使わないスレッドの停止方法を実装せよ。
    Class ThreadSafeStop
    Class SimpleSaftThread

という二つのクラスを実装する。


スケジューリングの観察

Java のスレッドのスケジューリングは実装に依存する。

Class Thread は、

 void	setPriority(int newPriority) 
          Changes the priority of this thread.

というメソッドを持っている。

このpriority を変更することによってスケジューリングを変更することができる。

このpriorityを変更して実行がどのようになるかを観察せよ。

    t1.setPriority(1);
    t2.setPriority(2);
    t3.setPriority(3);

priority の値は、任意の整数値ではない。いくつからいくつであるべきか。Java API document の中、あるいは、プログラムを作成して正しい範囲を調べよ。


Shinji KONO / Tue Dec 18 12:39:44 2007