开发者

Java Thread Wait-Notify

开发者 https://www.devze.com 2023-01-21 17:41 出处:网络
I have 3 threads (A, B, C) that i just can\'t make them work how i want them to. ALL these 3 threads share a reference to the same object - K.

I have 3 threads (A, B, C) that i just can't make them work how i want them to. ALL these 3 threads share a reference to the same object - K. What i'm trying to do, is to start all 3 up, then at some point in time when thread A arrives in a certain state, pause threads B and C, until A executes some method work() and when work finishes, resume B and C.

Now what i have in my code: Thread A has reference to both B and C. B and C hav开发者_开发问答e a method pause() { synchronized(K) { k.wait; }} When A arrives in that certain state, i call FROM A's run() method: B.pause(), C.pause(). Now what i'm expecting is that Threads B and C will waiT until someone makes a: k.notifyAll(), BUT instead Thread A stops. Is this normal in java ?

Code:

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();}
   }
}


You can use a CylcicBarrier to implement this.

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.
    }
}


When you call B.pause(), it is executed in the local thread, not in the thread where you called run method of B. There are some deprecated methods on the Thread class to do that but they are dangerous, see here: http://download.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html


Are you sure that you call b.pause() but declare B.sleep() ?

Would be nice to see threads construction/start code.


You know that you are using 3 diferent objects (monitors) A.k,B.k,C.k ?

So when B "paused" it synchronized on their own monitor (B.k) that should be free anyway. Your threads do not "communicate" in any way.


Remove the calls to b.pause() and c.pause() from A.run() and call them from their own run methods.


Unless I am misunderstanding your homework assignment, what I think you need to do is learn how to interrupt a thread. B and C are interruptable threads that need to handle the interrupt in such a way that they will not resume until they have been told it is OK. It could look something like this:

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...
      }
   }
}

So object A running in its own thread will have references to two other threads. Object A will have access to a shared monitor object that the runnables in the two other threads also have access to (I called it monitor). When A interrupts the other threads their runnables will then call wait() on the monitor. When A is done it will call notifyAll() on the monitor. NOTE you should clear the interrupt flag in the other threads too, but I leave that to you to figure out - its easy :)


I don't normally help with homework in this detail, but I think you are using the wrong approach anyway, so I don't see the harm in helping you do something you almost certainly shouldn't be doing :)

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;
   }
}

I'm guessing that what you really want to do though is unconditionally call wait in on k in B and C and then always call notifyAll in A

0

精彩评论

暂无评论...
验证码 换一张
取 消