• ベストアンサー

スレッド1とスレッド2を交互に実行するには?

スレッド1→スレッド2→スレッド1・・・と同期を取り合いながら交互にスレッドを動かしたいのですが、Thread.getState()を用いないで実現するよい方法はないでしょうか? どうしてもデッドロックが発生しうる方法しか思いつかず困っています。 例えば以下のプログラムで1212と交互に表示させたい場合です。 以下のプログラムは当然デッドロックになりますが、やりたいことを伝えるために載せておきます。 Object obj; //スレッド間通信用のobject class Test1 extends Thread {  public void run() {   while(true) {    System.out.print("1");    synchronized (obj) {     obj.notify();//相手をnotifyして     obj.wait();//自分はwait    }   }  } } class Test2 extends Thread {  public void run() {   while(true) {    System.out.print("2");    synchronized (obj) {     obj.notify();     obj.wait();    }   }  } } new Test1().start(); new Test2().start();

  • Java
  • 回答数2
  • ありがとう数2

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

  • ベストアンサー
noname#39970
noname#39970
回答No.1

スレッド1・2を監視するスレッド3を作って3が1・2を交互に呼ぶ  じゃだめ?

hekkusyoi
質問者

お礼

ありがとうございます。 方法の1つとして考えてみますが、なるべく2つのスレッドのみで実現したいです。 2つのスレッドでこういうことが不可能!ということが証明されているならばあきらめがつくのですが・・・。

その他の回答 (1)

  • dyna_1550
  • ベストアンサー率34% (122/353)
回答No.2

「交互に」という状態を、お互いから参照できる仕組みを作る必要があるということですね? かならず交互であるなら、スレッドは1つで、オブジェクト自身が状態を 交互に変化させるのではだめなのでしょうか?

hekkusyoi
質問者

お礼

質問はやりたいことを単純化したものなので、状態を変化させるという方法は使えません。 ただ、交互に処理を行いたい場合に状態を使う方法もありますね。 参考になりました。 先ほど色々試行錯誤した結果解決できたので締め切らせていただきます。 以下の方法で実現しました。 Object obj1; //スレッド間通信用のobject Object obj2; //スレッド間通信用のobject2 class Test1 extends Thread {  public void run() {   while(true) {    System.out.print("1");    synchronized (obj1) {     synchronized (obj2) {      obj2.notify();//相手をnotifyして     }     obj1.wait();//自分はwait    }   }  } } class Test2 extends Thread {  public void run() {   while(true) {    System.out.print("2");    synchronized (obj2) {     synchronized (obj1) {      obj1.notify();     }     obj2.wait();    }   }  } }

関連するQ&A

  • 交互にスレッド実行 (どうしてちゃんと動いてる?)

    http://oshiete1.goo.ne.jp/qa2968378.html で質問した者です。 2つのスレッドで1と2を交互に実行する以下のプログラム。 final Object obj1 = new Object(); //スレッド間通信用のobject final Object obj2 = new Object(); //スレッド間通信用のobject2 Thread t1 = new Thread() {  public void run() {   try {    while(true) {     System.out.print("1");     synchronized (obj1) {      synchronized (obj2) {       obj2.notify();//相手をnotifyして      }      obj1.wait();//自分はwait     }    }   } catech (Exception e){} }; Thread t2 = new Thread() {  public void run() {   try {    while(true) {     System.out.print("2");     synchronized (obj2) {      synchronized (obj1) {       obj1.notify();      }      obj2.wait();     }    }   } catch (Exception e){}  } }; Thread t1 = new Test1(); Thread t2 = new Test2(); t1.start(); while(t1.getState() != Thread.State.WAITING); t2.start(); が思ったように動いてはいるものの、なぜ正常に動いているかがわかりません。 t1が wait() したときはobj1のロックをもっていて、t2の synchronized (obj1){obj1.notify()} ブロックに入れず待機するはずだと思うのですが。 なぜちゃんと動いているのでしょう?

    • ベストアンサー
    • Java
  • wait()したスレッドが起こされるタイミング

    以下のコードにおいて。 % java ThreadWaitTest 2 の場合はaと表示したまま止まりますが、 % java ThreadWaitTest 1 の場合はスレッドの終了に伴ってwait()が切れ、bまで表示します。 私の望む動作は前者です。 後者の場合、これはつまりスレッドをwaitした際の待機プールがスレッドオブジェクトの場合、そのスレッドの実行が終了すると待機プールにある待機スレッドを自動でnotify()してしまうことを意味していると思うのですが、この解釈はあっていますか? Java のAPIドキュメントに 「別のスレッドが notify メソッドまたは notifyAll メソッドを呼び出してこのオブジェクトのモニター上で待機するスレッドに通知を出すまで待機します」 とあるように、ユーザが明確的にnotifyしないと起こらないと思いこんでいました。 なぜこういう仕様になっているのでしょうか? また、この仕様について詳しく書いてあるサイトやドキュメントなどありませんでしょうか? public class ThreadWaitTest extends Thread {  public Object mutex = new Object();    public static void main(String[] args) {   try {    ThreadWaitTest test = new ThreadWaitTest();    test.start();    System.out.println("a");    switch (new Integer(args[0])) {    case 1:     synchronized(test) {      test.wait();     }     break;    case 2:     synchronized(test.mutex) {       test.mutex.wait();     }     break;    }    System.out.println("b");   } catch (InterruptedException ie) {    ie.printStackTrace();   }  }  public void run() {   try {    Thread.sleep(5000);   } catch (InterruptedException ie){    ie.printStackTrace();}   } }

    • ベストアンサー
    • Java
  • スレッド間の送受信のコードについて

    下記のコードは、(以前お教え頂きました)『synchronized』を使用した、スレッド間の 送受信のコードですが、その代わりに、Interruptとか、Thread.sleep()を使用した、 コードに変更してみたいと思います。 Q1)そのコードをお教え頂けないでしょうか? class T_thread { public static void main(String args[]) { new rcvInterrupt().start(); } } class genInterrupt extends Thread { private rcvInterrupt target; genInterrupt(rcvInterrupt targetx) { this.target = targetx; } public void run() { System.out.println("genInterupt start"); for (int i = 0; i < 10; i++) { while (!target.isWaited) { // rcvInterruptがsynchronizedブロックに入るまで待ち合わせ // これがないと連続してsynchronizedしてしまう可能性がある } synchronized (target) { target.notifyAll(); target.isWaited = false; System.out.println("notify"); } } } } class rcvInterrupt extends Thread { volatile boolean isWaited; public synchronized void run() { new genInterrupt(this).start(); for (int i = 0; i < 10; i++) { try { isWaited = true; wait(); System.out.println("get interrupt cnt=" + i); } catch (InterruptedException e1) { } } } } 以上

    • ベストアンサー
    • Java
  • javaのwaitしてるスレッドをnotifyで起こすことが出来ない

    JDK1.5 WindowsXPです。 現在マルチスレッドを試しています。 A、B、C三つのスレッドがあります。 AはBというスレッドを作るメインスレッドです。 Bは、waitするスレッドです。 public final void run(){  while (true){   try {    //notifyが来るまで待機    waitForNotify();    //実際の処理    act();    //スレッド停止させるための割り込み例外   } catch (InterruptedException e) {    Thread.currentThread().interrupt();    e.printStackTrace();   }   //割り込み受信の場合強制終了する   if (Thread.currentThread().isInterrupted()) {    break;   }  } } こんな感じです。 そしてCのスレッドがnotify()を実行します。 しかしnotify()を実行してもスレッドは起きません。 Bに、 public synchronized void notifyM() throws InterruptedException{   wait(); } のようなメソッドを追加して、スレッドのインスタンスメソッドとして実行しても起きません。 notify()がJavaDOCなどを読んでも意味不明なため、 どのような使い方なら動くのか見当がつきませんので質問しました。 notify(スレッドB)みたいなら分かりいいんですが。

    • ベストアンサー
    • Java
  • wait中にinterruptを呼ばれたスレッドの振る舞いについて

    はじめまして。javaの初心者です。 どうしてもわからないことがあります。 例えば、以下のコードで、 class Foo { public synchronized void foo() { while(条件) { try { this.wait(); } catch(InterruptedException ex)    {     処理    } } } } wait中であったスレッドは、他のスレッドによって interrupt()メソッドを実行されたときは、Fooの ロックを取得してからcatch節を実行すると思うのですが、もし、以下のコードの場合は、 class Foo { public synchronized void foo() throws InterruptedException { while(条件) { this.wait(); } } } wait中であったスレッドは、他のスレッドによって interrupt()を実行されたときにすぐにInterrupted Exceptionをスローするのか、それとも Fooクラスのロックを取得してからInterruptedExceptionをスローするのかどちらなのか がわかりません。どうか教えてください。よろしく お願いします。

    • ベストアンサー
    • Java
  • デッドロックに関して1

    下記のサンプルソースは、デッドロックを起こすソース なのですが、 public class Deadlock extends Thread { public static Object l1 = new Object(); public static Object l2 = new Object(); private int index; public static void main(String[] a) { Thread t1 = new ThreadA(); Thread t2 = new ThreadB(); t1.start(); t2.start(); } private static class ThreadA extends Thread { public void run() { synchronized (l1) { System.out.println("スレッド1: l1に対するロックを取得"); try { Thread.sleep(10); } catch (InterruptedException e) {} System.out.println("スレッド1: l2のロックの開放待ち"); synchronized (l2) { System.out.println("スレッド1: l1、l2に対するロックを取得"); } } } } private static class ThreadB extends Thread { 文字数オーばーのため削除 } これを参考に、Junitでデッドロックを起こすサンプルを作りたいです。 MultithreadedTestCaseと ControllableTestThreadを使い サンプルを作りたいのですが、 英語が良くわからず苦戦しております。 なにか、よいアドバイスをいただけませんでしょうか? よろしくお願いします

    • ベストアンサー
    • Java
  • スレッドの待機と再開

    お世話になります。 マルチスレッドのプログラムで悩んでいます。 public class ThreadLocker {  private static boolean isLocked = false;    public static void lock() {   isLocked = true;   while(isLocked) { ; }  }    public static void unlock() {   isLocked = false;  } } まず、このようなクラスを定義しました。そして複数のスレッドが ThreadLocker.lock(); を呼び出して、処理の進行をストップしている状態があるとします。この状態に対して、とある別のスレッドが ThreadLocker.unlock(); を呼び出すと、それまで無限ループしていたスレッドが解放されて処理を始める、という感じです。 この方法を試してみましたが、無限ループで何も処理をしていないとは言え、リソースを食いまくっているようで、マシンが重くなってしまいました。 そこで、スレッドの待機・再開を行う事ができる wait / notify(All?) メソッドを使用すれば良いのではないかと考えたのですが、具体的な方法が分からず、質問させていただきました。 具体的に、どのインスタンスの wait 及び notify(All?) を呼び出せば良いのかが分かりません。 APIリファレンスの「現在のスレッドはこのオブジェクトのモニターのオーナでなければなりません。」の意味もよく分かりません。 ちなみに、待機しているスレッドは複数あり、class Lock の method execute 中で ThreadLocker.lock() しているとします。 また、再開を促すスレッドは1つで、class Unlock の method execute 中で ThreadLocker.unlock() を呼び出すものとします。 そして、それぞれのスレッドは、お互いのインスタンスを知りません。(説明しづらいので、補足要求があれば、ソースで示します。) よろしくお願いいたします。

    • ベストアンサー
    • Java
  • スレッドが実行中かどうかの確認

    画面の中にボタンを作成し、そのボタンを押すとスレッドが実行される機能を作成しました。 「一度ボタンを押してスレッドが実行中の場合は処理を実行しない」 という処理を実装したいです。 上記の処理を以下のソースで考えていますが(1)の部分がわかりません。 そもそも(1)のようなことが可能かもわかっていない状況です。 (1)のようなことは可能なのでしょうか? どなたか、知恵を貸していただければと思います。 よろしくお願い致します。 /* ソース */ public class ExThread1 extends Thread{  public void run() {   // 処理  } } public class TEST {  public static void main(String[] args){   ExThread1 thread1 = new ExThread1();   // (1)スレッドが実行中ならstartしない   if(スレッドが実行中ではない){    thread1.start();   }  } }

    • ベストアンサー
    • Java
  • Javaのスレッドに関して質問です

    Assistantクラスを使い待機状態と再開を確認できるプログラムの作成 loafとrestartメソッドを設ける workメソッドが呼ばれる度loafを呼び出す Managerクラスを定義 checkメソッドを設け、Assistantをcheckし続ける loaf状態ならrestartさせる (Managerクラスはデーモンスレッド) ということなんですが、いまいちうまくいきません さぼっても復帰してくれません public class Assistant implements Runnable { private String name; private Chore c; 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() { try { c.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void restart() { c.notify(); } } public class Chore { private String name; private int step; private int id; public Chore(String name) { this.name = name; this.step = this.name.length(); this.id = 0; } public synchronized String digest() { String message = "" + id + name.charAt(id); try { Thread.sleep(500); } catch (InterruptedException ie) { } id++; return message; } public synchronized boolean doEnd() { return id >= step; } } public class Manager extends Thread { private String name; private Assistant a; public Manager(String name) { this.name = name; } public void run() { check(); } public void check() { a.restart(); } } public class Test { public static void main(String[] args) { Chore[] ch = { new Chore("掃除"), new Chore("プリント印刷"), new Chore("出欠データ入力") }; Assistant[] a = { new Assistant("あ", ch[0]), new Assistant("\tい", ch[1]), new Assistant("\t\tう", ch[2] }; Thread[] t = new Thread[a.length]; for (int i = 0; i < t.length; i++) { t[i] = new Thread(a[i]); } for (int i = 0; i < t.length; i++) { t[i].start(); } Manager m = new Manager("監査"); m.setDaemon(true); m.start(); for (int i = 0; i < t.length; i++) { try { t[i].join(); } catch( InterruptedException ie ) { } } }

    • ベストアンサー
    • Java
  • スレッド動かず

    本の真似をして、スレッドを書いてみたんですがに何も起こりませんでした。全く分かりません。どうすれば良いでしょうか? public class Frame1 extends Frame implements Runable{ ................. ................. Thread kick = new Thread(this); int time; public void start() { if (kick ==null) kick.start(); } public void run() { while (kick == Thread.currentThread()) { time++; String s = Integer.toString(time); textArea1.append( s + "\r\n"); try{ Thread.sleep(1000); }catch(InterruptedException e){} } }

    • ベストアンサー
    • Java