• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:Javaのスレッドに関して質問です)

Javaのスレッドに関する質問と解決方法

このQ&Aのポイント
  • Javaのスレッドを使用したプログラムで待機状態と再開を確認する方法
  • Assistantクラスにloafとrestartメソッドを設けて、workメソッドが呼ばれるたびにloafを呼び出す
  • ManagerクラスのcheckメソッドでAssistantの状態を確認し、loaf状態ならrestartを呼び出す

質問者が選んだベストアンサー

  • ベストアンサー
  • hirotn
  • ベストアンサー率59% (147/246)
回答No.9

自環境(Windows7、32bit)で発現しないため、詰まっています。 waitかnotify...  ManagerクラスのcheckメソッドのExceptionをキャッチする段にスタックトレースを仕掛けて、 }catch (Exception e){ e.printStackTrace(); } 何行目かって分かりますか? 貴実行環境も参考までに教えていただきたいです。 あるいは、 >javac -g Test0715.java でコンパイルし、 jdbで例外発生時のスレッドの実行状況を把握するために以下のコマンドを投入してスタックトレースを見たいです。 >jdb Test0715 >catch IllegalThreadStateException >run で実行 IllegalThreadStateExceptionをキャッチしたら >suspend >where all ←このコマンドの出力結果をいただきたいです。

criminal1006
質問者

お礼

提出期限が過ぎてしまったので、 締切とさせていただきます。 今までの回答ありがとうございました。

その他の回答 (8)

  • hirotn
  • ベストアンサー率59% (147/246)
回答No.8

現状のソースがどうなっているのかを拝見したいです(エラーが出るソース)。

criminal1006
質問者

補足

あなたがくださったソースを実行しました。 コンパイルはとおりますが、実行途中で先ほど言った症状が出ます

  • hirotn
  • ベストアンサー率59% (147/246)
回答No.7

waitはloafのなかでしています。 Managerのcheckが絶えずチェックし続けるため、waitしていないように見えます。 Managerのcheckメソッドを以下のように編集して、sleepを追加すると、チェック間隔が広くなり、Assistantのwaitも把握できると思います。 public void check() { try{ while(!stop){ for (int i = 0; i < t.length ; i++){ System.out.println(i + " - " + t[i].getState()); if(t[i].getState() == Thread.State.WAITING) a[i].restart(); } try { Thread.sleep(1000); } catch (InterruptedException ie) { } } }catch (Exception e){ System.out.println(e.toString()); } } これでも違和感があれば、求める実行結果を詳しく教えていただきたいです。

criminal1006
質問者

補足

実行してみたのですが、 一番目のスレッドがwaitされてnotifyされたとこまでは確認出来ましたが、 そのあと、IllegalThreadStateExceptionが発生し、エラーの嵐になります

  • hirotn
  • ベストアンサー率59% (147/246)
回答No.6

http://kie.nu/197g パスワード:oshiete 現作業ソースです。 - 1ファイルに抑えるため、パブリッククラスはmain以外ただのclassにしています。 - 当方のファイル管理上Test0715をmainメソッドのクラスとしています。 (実行結果)以下を出力して終了…これが正しいかもわかっていませんが。 う : 0出 い : 0プ あ : 0掃 う : 1欠 い : 1リ あ : 1除 い : 2ン う : 2デ い : 3ト う : 3ー い : 4印 う : 4タ い : 5刷 う : 5入 う : 6力

criminal1006
質問者

補足

これいつwaitしてるんどすか?

  • hirotn
  • ベストアンサー率59% (147/246)
回答No.5

では、AssitantクラスのnotifyAllをnotify()に変えて、 public synchronized void restart() { notify(); } Managerクラスを以下のようにしてみます。 class Manager extends Thread { private String name; private Thread[] t; private Assistant[] a; public boolean stop = false; class Manager extends Thread { public Manager(String name, Thread[] t, Assistant[] a) { this.name = name; this.t = t; this.a = a;} public void run() { check(); } public void check() { try{ while(!stop){ for (int i = 0; i < t.length ; i++){ if(t[i].getState() == Thread.State.WAITING) a[i].restart(); } } }catch (Exception e){ System.out.println(e.toString()); } } } これで前回答のisWaitは不要です。本来はスレッドの状態を見たかったのでこうすべきでしょう。

criminal1006
質問者

補足

これだと最初に実行されたスレッドにしか適応されず、止まったままになってしまいます。 ManagerのstartをAssistantのスレッドのループ終了後の実行していますがうまくいきません

  • hirotn
  • ベストアンサー率59% (147/246)
回答No.4

public Assistant(String name, Chore c) { this.name = name; this.c = c; } public void run() { work(); } public void work() { while (true) { synchronized(c){ if (c.doEnd()) break; System.out.println(name + " : " + c.digest()); } loaf(); } } public synchronized void loaf() { isWait = true; try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } isWait = false; } public synchronized void restart() { if (isWait) { notifyAll(); } } } class Manager extends Thread { private String name; private Assistant[] a; public boolean stop = false; public Manager(String name, Assistant[] a) { this.name = name; this.a = a;} public void run() { check(); } public void check() { try{ while(!stop){ for (int i = 0; i < a.length ; i++){ a[i].restart(); } } }catch (Exception e){ System.out.println(e.toString()); //例外が発生して、こちらに落ちた→ループ抜けてスレッドも死んだ } } } Testクラス: 変更1 Managerクラスの生成は、Manager m = new Manager("監査", a);として、Assistantクラスを渡しています。 変更2 joinのループを抜けた後に以下を追加 m.stop = true; (1)Managerクラスにチェックし続ける処理(と抜ける条件)を追加 (2)waitをスレッドを眠らせる (3)起こすときは一度に全員起こす なぜChoreのインスタンスにwaitを掛けていたのかが謎だったので、スレッドを寝かすようにさせて頂きました。意図がありますか?

criminal1006
質問者

補足

いえ、私のミスです。 すみません。 1つ訂正なのですが、Managerクラスがスレッドを順番に見ていき、眠っていたら起こすようにするなので、全員起こすではないです。 notifyAllは使わないです。

  • teketon
  • ベストアンサー率65% (141/215)
回答No.3

>checkメソッドを設け、Assistantをcheckし続ける これをやってないです。 クラスTest内のAssistantインスタンスとManagerインスタンス間に、 何の関連も作られてないので、Managerのcheckメソッドが機能していません。

criminal1006
質問者

補足

Assistantの配列をManagerに渡してやってもみたのですが、 どうもうまくいきません。 まず、Managerのstartメソッドをループさせ続けなければいけませんし

  • hirotn
  • ベストアンサー率59% (147/246)
回答No.2

私の前回答は破棄してください。申し訳ありません。 アシスタントスレッドを起こすタイミング(notify)が一度しかありませんでした。この時はIllegalMonitorStateExceptionが発生しています。 そしてそのタイミングは、アシスタントスレッドを起こした直後にで、その後発生せず、main内のjoinに入るため、Manager - mainも待ちに入ります。 こうして全てのスレッドが待ち状態になり、プロセスそのものがストップした状態になったプログラムとなってしまっています。 解決策は考えてみますが、設計し直しも必要かもしれません。

criminal1006
質問者

補足

クラス設計は変えずになので、 メソッドの中身を変えるしか方法はないです。

  • hirotn
  • ベストアンサー率59% (147/246)
回答No.1

public void check() { a.restart(); } ここだけa.restartなのが気になります。他はt[i].methodnameなので。

criminal1006
質問者

補足

そのへんはとりあえずAssistantクラスをManagerクラスが持っておいて、Assistantクラスのrestartメソッドを呼び出すためにやっています。 今は一旦Manager関連はいったんコメントアウトして、Assistantクラスのworkメソッドで、loafを呼び出した後にrestartメソッドを呼び出しているのですが、呼ばれなく詰んでいるところです。

関連するQ&A

専門家に質問してみよう