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()。现在我期待的是线程 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();}
   }
}
4

7 回答 7

3

您可以使用CyclicBarrier来实现这一点。

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() 但声明 B.sleep() 吗?

很高兴看到线程构造/启动代码。

于 2010-10-20T15:09:29.363 回答
0

您知道您正在使用 3 个不同的对象(监视器) Ak、Bk、Ck 吗?

因此,当 B“暂停”时,它会在他们自己的监视器 (Bk) 上同步,无论如何该监视器应该是免费的。您的线程不会以任何方式“交流”。

于 2010-10-20T15:16:44.447 回答
0

删除对b.pause()c.pause()来自的调用,并A.run()从它们自己的运行方法中调用它们。

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

于 2010-10-20T16:59:03.357 回答
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;
   }
}

我猜你真正想做的是无条件地调用 wait ink然后B总是C调用 notifyAll inA

于 2010-10-21T06:40:19.170 回答