Java线程等待通知

时间:2010-10-20 15:03:54

标签: java multithreading wait notify

我有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()。 现在我期待的是线程B和C将会消失,直到某人做出:k.notifyAll(),但是线程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();}
   }
}

7 个答案:

答案 0 :(得分: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.
    }
}

答案 1 :(得分:1)

当你调用B.pause()时,它在本地线程中执行,而不是在你调用B的run方法的线程中执行。 Thread类上有一些不赞成使用的方法,但是它们很危险,请看这里: http://download.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html

答案 2 :(得分:0)

你确定你调用b.pause()但声明B.sleep()吗?

很高兴看到线程构造/开始代码。

答案 3 :(得分:0)

你知道你使用的是3个不同的对象(监视器)A.k,B.k,C.k?

所以,当B“暂停”它在他们自己的显示器(B.k)上同步,无论如何都应该是免费的。 你的主题没有以任何方式“沟通”。

答案 4 :(得分:0)

b.pause()移除对c.pause()A.run()的来电,并使用自己的运行方式调用它们。

答案 5 :(得分:0)

除非我误解你的家庭作业,否则我认为你需要学习如何打断一个线程。 B和C是可中断的线程,需要以这样一种方式处理中断,即在被告知它没有问题之前它们不会恢复。它可能看起来像这样:

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可以访问共享的监视器对象,其他两个线程中的可运行对象也可以访问它(我称之为monitor)。当A中断其他线程时,它们的runnable将在监视器上调用wait()。 A完成后,它将在监视器上调用notifyAll()。注意你也应该清除其他线程中的中断标志,但我把它留给你弄清楚 - 很容易:)

答案 6 :(得分:0)

我通常不会在这个细节上帮助做作业,但我认为你无论如何都在使用错误的方法,所以我没有看到帮助你做一些你几乎肯定不应该做的事情的伤害:)< / p>

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

我猜你真正想做的事情是无条件地在kBC呼叫等待,然后始终在A中呼叫notifyAll / p>