簡體   English   中英

Java線程等待通知

[英]Java Thread 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的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();}
   }
}

您可以使用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.
    }
}

當您調用B.pause()時,它是在本地線程中執行的,而不是在您調用B的run方法的線程中執行的。Thread類上有一些不贊成使用的方法,但是這樣做很危險,請參見此處: http ://download.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html

您確定調用b.pause()但聲明B.sleep()嗎?

很高興看到線程的構造/啟動代碼。

您知道您正在使用3個不同的對象(監視器)Ak,Bk,Ck嗎?

因此,當B“暫停”時,它會在自己的監視器(Bk)上同步,該監視器無論如何都應該是空閑的。 您的線程不會以任何方式“通信”。

取下調用b.pause()c.pause()A.run()並從自己的運行方法調用它們。

除非我對您的家庭作業有誤解,否則我認為您需要做的是學習如何中斷線程。 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() 注意您也應該清除其他線程中的中斷標志,但是我讓您自己弄清楚-這很容易:)

我通常不會在這個細節上幫助家庭作業,但是我認為您無論如何都使用了錯誤的方法,因此我認為幫助您做您幾乎肯定不應該做的事情沒有害處:)

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

我猜想您實際上想要做的是無條件地在BC k上等待,然后總是在A調用notifyAll

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM