-title: Java Thread 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 の中、あるいは、プログラムを作成して正しい範囲を 調べよ。