2012-10-21 4 views
6

JavaでRunnableを実装するクラスを持つことができ、クラスのオブジェクトがwait()になるとスレッドが信号を受け取るまで実行を停止するかどうか疑問に思っています。同じクラスの別のオブジェクトが実行を継続するように通知できますか?理想的には私が行うことができるようにしたいものをどのように私はwait/notifyAllを使用するのですか?

は次のようになります。これは可能とどのように私はそれをやって行くだろうもしそうなら

public class ThreadClass implements Runnable{ 

public void run(){ 
//.. Does some arbitrary work 

    if(aCondition){ //have it wait until something signals it to contine exection. 
this.wait(); 
} 

//Continues to do more work. 

//finished whatever it needed to do. Signal all other threads of this object type to continue their work. 
this.notifyAll(); 

} 
} 

ですか?オブジェクト自体が同じタイプのオブジェクトや他のすべてのオブジェクトを管理できるようにしようとしています。このクラスを使用する誰もそれを管理することを心配する必要はありません。

答えて

6

オブジェクト自体が同じタイプのオブジェクトを管理できるようにしようとしています。このクラスを使用する誰もそれを管理することを心配する必要はありません。

あなたはすべてのインスタンスを作成する場合

は、ほぼすべての他のインスタンスを知って、あなたは、静的なガベージコレクションがトリッキーになりコレクション...だけでなく、それはすべてのハードテストすることのいくつかの並べ替えを必要とするだろう。

あなたは、このクラスのインスタンスを管理することが唯一の仕事である別のマネージャタイプをお勧めします。次に、ロジックを1つの場所に配置するだけですが、タイプのすべてのインスタンスについて知る必要はありません。マネージャは、管理しているものを知るだけで済みます。クライアントコードのみがにマネージャを表示する必要があり、個々のインスタンスが非表示になるようにAPIを作成することもできます。

EDIT:だけ明確にする、あなたもまったくwait/notifyAllを必要としないかもしれない - あなたは、このようなwaitのような低レベルの操作なしでプロデューサ/コンシューマのシナリオを書くことができjava.util.concurrentでより高いレベルの構造を、好みます。この回答は、オブジェクトが通信しなければならない他のオブジェクトを知らせるという、より高いレベルの問題に対処しています。あるタイプのすべてのオブジェクトが別のタイプのものを知っているという質問の考え方は、問題につながるので、マネージャークラスの提案につながります。

+0

どのようにマネージャを作成するのに役立ちますか?現在のところ、スレッドオブジェクトを作成するクラスは1つしかありませんが、すべてのスレッドが一時停止するわけではありません。リソースが別のスレッドによって解放されるまで、約1/10のスレッドが停止する必要があります。 – user597608

+0

@ user597608:もっと情報を知る必要があります。私たちは、これが何をしようとしているのか、本当に分かりません。マネージャーに各インスタンスの作成を担当させることができれば、それぞれのインスタンスに参照を渡すことができるので、同じマネージャーが管理する他のインスタンスに何かを通知する必要があるときにコールバックできます...それはあなたを助ける? –

+0

私はUDPコールを待っているサーバを作っています。メッセージを取得し、メッセージを解析してSQLiteデータベースに入力する新しいスレッドを作成します。 sqliteデータベースがファイルであるため、データベースがロックされるという問題が発生しています。接続プール(BoneCP)を試しましたが、コードのパフォーマンスが1/10に低下しました。現時点では、私のサーバは10 msg /秒を処理できますが、これ以上のものはありません。 – user597608

1
If(condition) 
{ wait } 

理想的には、ブロックではなく条件で囲む必要があります。クライアントは通知に頼るのではなく、先に進む前に条件が満たされていることを確認する必要があるからです。

1

それ自体を管理することによって、ロックによって同期を管理し、状況によってはインスタンス変数の境界に従うことを意味する可能性があります。

public class ThreadClass implements Runnable { 

    public void run() { 
     // .. Does some arbitrary work 
     synchronized (this) { 
      while (! aCondition) { // have it wait until something signals it to 
           // contine exection. 
       this.wait(); 
      } 
     } 

    /* Reset the aCondition var to its old value to allow other threads to 
     enter waiting state 

     Continues to do more work. 

     Finished whatever it needed to do. Signal all other threads of this 
     object type to continue their work.*/ 
     synchronized (this) { 
      this.notifyAll(); 
     } 

    } 
} 

また、Conditionインターフェイスも参照してください。これは、java.util.concurrentクラスを使用する以外はまったく同じ要件を持つようです。 BoundedBufferの例があります。

下記のプロデューサコンシューマの例を参照してください。同じ待機/通知テンプレートを持ちます。使用可能なフラグはvolatile宣言されているため、スレッドセーフな読み取りと書き込みを実行できます。

public class ProducerConsumerTest { 
    public static void main(String[] args) { 
     CubbyHole c = new CubbyHole(); 
     Producer p1 = new Producer(c, 1); 
     Consumer c1 = new Consumer(c, 1); 

     p1.start(); 
     c1.start(); 
    } 
} 



    class CubbyHole { 
     private int contents; 
     private volatile boolean available = false; 

     public int get() { 
      synchronized (this) { 
       while (available == false) { 
        try { 
         wait(); 
        } catch (InterruptedException e) { 
        } 
       } 
      } 

      available = false; 
      synchronized (this) { 
       notifyAll(); 
      } 
      return contents; 
     } 

     public void put(int value) { 
      synchronized (this) { 
       while (available == true) { 
        try { 
         wait(); 
        } catch (InterruptedException e) { 
        } 
       } 
      } 
      available = true; 

      contents = value; 

      synchronized (this) { 
       notifyAll(); 
      } 
     } 
    } 

    class Consumer extends Thread { 
     private CubbyHole cubbyhole; 
     private int number; 
     private Integer takeSum = new Integer(0); 

     public Consumer(CubbyHole c, int number) { 
      cubbyhole = c; 
      this.number = number; 
     } 

     public Integer getTakeSum() { 
      return takeSum; 
     } 

     public void run() { 
      int value = 0; 
      for (int i = 0; i < 100; i++) { 
       value = cubbyhole.get(); 
       takeSum+=value; 

      } 

      System.out.println("Take Sum for Consumer: " + number + " is " 
        + takeSum); 
     } 
    } 

    class Producer extends Thread { 
     private CubbyHole cubbyhole; 
     private int number; 
     private Integer putSum = new Integer(0); 

     public Integer getPutSum() { 
      return putSum; 
     } 

     public Producer(CubbyHole c, int number) { 
      cubbyhole = c; 
      this.number = number; 
     } 

     public void run() { 
      for (int i = 0; i < 100; i++) { 
       int rnd = (int) (Math.random() * 10); 
       cubbyhole.put(rnd); 
       putSum+=rnd; 
       try { 
        sleep((int) (Math.random() * 100)); 
       } catch (InterruptedException e) { 
       } 
      } 
      System.out.println("Put Sum for Producer: " + number + " is " + putSum); 

     } 
    } 
+0

これを試して、 – user597608

+0

CubbyHoleプロデューサ - コンシューマの例は、待機/通知メカニズムを理解するのに良い方法です。上記のテンプレートと同じテンプレートで行っています。 – clinton

1

あなたは、同じクラスの別のオブジェクトの動作を続行するためにそれを通知することができ

を尋ねましたか?

絶対にはい! - オブジェクトがこのオブジェクトを待ってブロックされている場合、からのインスタンスがのいずれかのクラスから呼び出されます。 (自身を待っているRunnableを含む)

notifyAllは通知するクラスの型を気にせず、このオブジェクトを待機しているすべてのクラスに通知します。 (これをロックとして使用する)。

そのため、任意のクラスのインスタンスは、任意のオブジェクトに対して待機または通知を呼び出すことができます。 waitおよびnotifyはjava.lang.Objectのパブリックメソッドです

このチュートリアルを参照してください。

http://www.java-samples.com/showtutorial.php?tutorialid=306

+0

OPは、質問が間違っている " - 彼はそれを望んでいないコードを掲載していますが、それは同じことではありません。 –

関連する問題