[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[jfriends:00497] Re: Thread の一時停止と再開について
吉田です。
At 31 Oct 2001 16:54:29 +0900 Titta2@xxxxxxxxxxxx writes
>
>信乃です。
>
>>Threadクラスのインスタンス(オブジェクト)とスレッドを分けて考えてください。
>すみません。同じものとして捉えてました。
>
>>thはThreadクラスのオブジェクトで、thisはStop_Resumeクラスのオブジェクトを
>>指しています。
>それでsynchronized(object)をthisにするとおかしくなってしまうんですね・・・
>ようやく合点がいきました。
>
>何度もありがとうございました。
>大変勉強になりました。
私は、これを読んだときに、notify ではなく、 notifyAll を使う方が、いいので
はないかと思いました。
下記のJavaプログラム引数に、10 500 を与えてみると、
notifyでは、期待したスレッドが再開されない例外的なケースをシミュレート出来ます。
package test;
public class NotifyTest extends Thread {
public static Object mutex = new Object();
public static int notifyId = 0;
public static void main(String[] args) {
int maxThread = 10;
int sleepTime = 500;
try {
maxThread = Integer.parseInt(args[0]);
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println("args[0]でスレッドの数を指定出来ます");
}catch(NumberFormatException e) {
System.out.println("args[0]でスレッドの数を指定出来ます");
e.printStackTrace();
}
try {
sleepTime = Integer.parseInt(args[1]);
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println("args[1]で処理のウェイトを指定出来ます");
}catch(NumberFormatException e) {
System.out.println("args[1]で処理のウェイトを指定出来ます");
e.printStackTrace();
}
NotifyTest[] states = new NotifyTest[maxThread];
for(int i = 0; i < maxThread; ++ i) {
states[i] = new NotifyTest(i);
states[i].start();
}
try {
System.out.println("1秒後にテストを開始します");
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
return;
}
notifyId = maxThread - 1;
int term = 0;
for(int j = 0; j < 30; ++ j) {
try {
if(sleepTime > 0) Thread.sleep(sleepTime);
}catch(InterruptedException e) {
e.printStackTrace();
return;
}
try {
synchronized(mutex) {
System.out.println();
while(notifyId > 0 && states[notifyId].isHappy) {
notifyId --;
}
System.out.print("notify" + notifyId + " ");
mutex.notify();
}
}catch(IllegalStateException e) {
e.printStackTrace();
}
}
System.out.println();
while(states[0].isHappy == false) {
//for(int j = 0; j < 30; ++ j) {
try {
if(sleepTime > 0) Thread.sleep(sleepTime);
}catch(InterruptedException e) {
e.printStackTrace();
return;
}
try {
synchronized(mutex) {
System.out.println();
while(notifyId > 0 && states[notifyId].isHappy) {
notifyId --;
}
System.out.print("notifyAll" + notifyId + " ");
mutex.notifyAll();
}
}catch(IllegalStateException e) {
e.printStackTrace();
}
}
System.out.println();
}
private final int id;
public NotifyTest(int i) {
id = i;
setDaemon(true);
isHappy = false;
}
public void run() {
synchronized(mutex) {
try {
while(true) {
mutex.wait();
if(id == notifyId) {
System.out.print(":" + id + "=wanted");
isHappy = true;
break;
}
System.out.print(":" + id);
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
public boolean isHappy;
}
問題がもうひとつありまして、100 0 を与えてみると、notifyAllでも、目的の
スレッドが再開されない事がある様なので、notifyAll 後に、
前後関係によっては、Thread.yield() も必要なの物なのでしょうか。
#ひょっとして、FAQなのでしょうか。
#もしFAQで無いなら、なんとなくJavaのバグに見えてしまう。
#GUIなら問題はなさそうだけど・・
あるいは、isAliveによる検査方法がまずい?
sleepTime >= 1 の出力
134 行
notifyAll11 :4:9:1:0:6:11=wanted:7:8:10:2:3:5
notifyAll10 :4:9:1:0:6:7:8:10=wanted:2:3:5
notifyAll9 :4:9=wanted:1:0:6:7:8:2:3:5
notifyAll8 :4:1:0:6:7:8=wanted:2:3:5
notifyAll7 :4:1:0:6:7=wanted:2:3:5
notifyAll6 :4:1:0:6=wanted:2:3:5
notifyAll5 :4:1:0:2:3:5=wanted
notifyAll4 :4=wanted:1:0:2:3
notifyAll3 :1:0:2:3=wanted
sleepTime == 0 の出力 (sleepなし)
4554行
notifyAll10
notifyAll10
notifyAll10 :0:5:3:4:6:7:8:10=wanted:2:1:9
notifyAll9 :0:5:3:4:6:7:8:2:1:9=wanted
notifyAll8 :0:5:3:4:6:7:8=wanted:2:1
notifyAll7 :0:5:3:4:6:7=wanted:2:1
notifyAll6 :0:5:3:4:6=wanted:2:1
notifyAll5 :0:5=wanted:3:4
notifyAll4 :2:1
notifyAll4 :0:3:4=wanted
notifyAll3 :2:1
notifyAll3 :0:3=wanted
notifyAll2 :2=wanted:1
notifyAll1 :0
notifyAll1 :1=wanted
notifyAll0 :0=wanted
notifyAll0
notifyAllの場合と違い、notifyの場合には抜けがありません。
なので、キューイベントは、待機スレッド、キュー毎のObject、wait(), notify()だけで
ずいぶんスマートに実装できるのですね。
最後の2行は、whileからsynchronizedの間でダブルチェックしていないからですが、
他の重複部分がどこを通過しているのでしょうか。
synchronized(mutex) {
if(states[0].isHappy)
break;
}
きっと、パフォーマンスの関係で、notifyAllは、全てのスレッドに順番をゆずる前に、
自分自身にも、順番がまわって来るのだろうという事で納得します。
今作成している、アプリケーションで、wait, notify,が肝になっていますので、
いろいろ考えてしまいました。もし、FAQの様な物や、経験などございましたら、
いろいろお聞かせ願えれば幸いです。
--
S.Yoshida <vzy03312@xxxxxxxxxxxxxxxxx>
------------------------------------------------------------------------
★ こっちの流行語大賞はどんなの?
http://www.infoseek.co.jp/Keyword?pg=nranking_top_if.html&svx=971122