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