2

私は3つのスレッド(A、B、C)を持っていますが、それらを希望どおりに動作させることができません。これら3つのスレッドはすべて、同じオブジェクトへの参照を共有します-K。私がやろうとしているのは、3つすべてを起動し、スレッドAが特定の状態に到達した時点で、スレッドBとCを一時停止することです。 Aが何らかのメソッドwork()を実行するまで、そして作業が終了したら、BとCを再開します。

これで、コードに含まれるもの:スレッドAにはBとCの両方への参照があります。BとCにはメソッドpause(){synchronized(K){k.wait;があります。Aがその特定の状態に到達したら、FROM Aのrun()メソッドを呼び出します:B.pause()、C.pause()。今私が期待しているのは、誰かがk.notifyAll()を作成するまで、スレッドBとCは待機するということですが、代わりにスレッドAは停止します。これはJavaでは正常ですか?

コード:

class A implements Runnable {
   private K k;
   private B b;
   private C c;

   void run() {
      while(something) {
         //do something
         b.pause();
         c.pause();
          // !!! here this thread will freeze and doSomething2 wont get executed.
          // what i want is to pause B, C, doSomething2 to get executed and then resume B and C
         //do something2 
         synchronized(k) {
           k.notifyAll();
         }
      }
   }
}
class B implements Runnable {
   private K k;


   void run() {
      while(something) {
         //dome something
         }
      }
   }
   public pause() {
       synchronized(k) { k.wait();}
   }
}
class C implements Runnable {
   private K k;


   void run() {
      while(something) {
         //dome something
         }
      }
   }
   public pause() {
       synchronized(k) { k.wait();}
   }
}
4

7 に答える 7

3

CylcicBarrierを使用してこれを実装できます。

CyclicBarrier barrier = new CyclicBarrier();

public void run() {
    new Thread(new A(barrier)).start();
    new Thread(new B(barrier)).start();

    barrier.await();  // Waits until all threads have called await()

    // Do something
}

public void A implements Runnable {
    private CyclicBarrier barrier;

    public A(CyclicBarrier barrier) {
        this.barrier = barrier;
    }

    public void run() {
        barrier.await();
        // Do something.
    }
}

public void B implements Runnable {
    private CyclicBarrier barrier;

    public B(CyclicBarrier barrier) {
        this.barrier = barrier;
    }

    public void run() {
        barrier.await();
        // Do something.
    }
}
于 2010-10-20T15:16:05.433 に答える
1

B.pause() を呼び出すと、B の run メソッドを呼び出したスレッドではなく、ローカル スレッドで実行されます。Thread クラスには非推奨のメソッドがいくつかありますが、危険です。こちらを参照してください: http ://download.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html

于 2010-10-20T15:13:48.947 に答える
0

b.pause()c.pause()からの呼び出しを削除しA.run()、独自の実行メソッドから呼び出します。

于 2010-10-20T15:42:12.300 に答える
0

私は通常、この詳細について宿題を手伝うことはありませんが、とにかく間違ったアプローチを使用していると思います。したがって、ほぼ確実に行うべきではないことを行うのを手伝うことに害はないと思います:)

class A implements Runnable {
   private K k;
   private B b;
   private C c;

   void run() {
      while(something) {
         //do something
         b.pause();
         c.pause();
          // !!! here this thread will freeze and doSomething2 wont get executed.
          // what i want is to pause B, C, doSomething2 to get executed and then resume B and C
         //do something2 
         synchronized(k) {
           k.notifyAll();
         }
      }
   }
}
class B implements Runnable {
   private K k;
   volatile boolean isPaused = false;


   void run() {
      while(something) {
         if (isPaused) {
           synchronized(k) { k.wait();}
           isPaused = false;
         }
         //dome something
      }
   }
   public pause() {
     isPaused = true;
   }
}
class C implements Runnable {
   private K k;
   volatile boolean isPaused = false;


   void run() {
      while(something) {
        if (isPaused) {
          synchronized(k) {
            k.wait();
          }
          isPaused = false;
        }
        //dome something
      }
   }
   public pause() {
     isPaused = true;
   }
}

あなたが本当にやりたいことは、無条件に待機を呼び出してkからBC常にnotifyAllを呼び出すことだと思います。A

于 2010-10-21T06:40:19.170 に答える
0

b.pause()を呼び出しても、B.sleep()を宣言してもよろしいですか?

スレッドの構築/開始コードを見るといいでしょう。

于 2010-10-20T15:09:29.363 に答える
0

3 つの異なるオブジェクト (モニター) Ak、Bk、Ck を使用していることをご存知ですか?

そのため、B が「一時停止」すると、とにかく空いているはずの独自のモニター (Bk) で同期されました。あなたのスレッドは決して「通信」しません。

于 2010-10-20T15:16:44.447 に答える
0

私があなたの宿題を誤解していない限り、あなたがしなければならないことは、スレッドを中断する方法を学ぶことだと思います. B と C は割り込み可能なスレッドであり、OK と通知されるまで再開しないような方法で割り込みを処理する必要があります。次のようになります。

while(true)
{
   try
   {
      Thread.sleep(100);
      System.out.println("Thread is working normally...");
   }
   catch(InterruptedException e)
   {
      System.out.println("Thread has been interrupted, will wait till A is done...");
      try
      {
         synchronized(monitor)
         {
           monitor.wait();
         }
      }
      catch(InterruptedException e2)
      {
         // whatever...
      }
   }
}

そのため、独自のスレッドで実行されているオブジェクト A は、他の 2 つのスレッドへの参照を持ちます。オブジェクト A は、他の 2 つのスレッドのランナブルもアクセスできる共有モニター オブジェクトにアクセスできます (私はそれを と呼びましたmonitor)。A が他のスレッドに割り込むと、ランナブルがwait()モニターで呼び出されます。A が完了するとnotifyAll()、モニターに呼び出されます。注:他のスレッドでも割り込みフラグをクリアする必要がありますが、それはあなたに任せます-簡単です:)

于 2010-10-20T16:59:03.357 に答える