2011-12-18 24 views
2

スレッドがアクセスできるシングルトンクラスがあります。
各スレッドはこのクラスのインスタンスをロードし、ループ内でこのクラスのメソッドを呼び出します。スレッドを1つずつ実行する

すべてのスレッドがメソッドを呼び出すことができるように、実行の流れを制御する必要があります。 スレッドは、メソッドを任意の順序で呼び出すことができます。スレッドは、ループを移動する前にメソッドを一度実行しなければなりません。スレッドで

::私はやってみました何

これを

public synchronized void SomeMethod(String threadID) { 
hashMap.put(threadID,true); 
some job here 
} 

をしてwaitisneededに:

public synchronized boolean waitisneeded(){ 
{ 

    Iterator iter = hashMap.entrySet().iterator(); 

    boolean alldone = false; 

    while (iter.hasNext()) { 
     Map.Entry me = (Map.Entry) iter.next(); 
     String key = me.getKey().toString(); 
     alldone = (Boolean)me.getValue(); 

     if(!alldone) { 
    return false; 
     } 
    } 

    //set all values to false 
iter = hashMap.entrySet().iterator(); 
while (iter.hasNext()) { 
    Map.Entry me = (Map.Entry) iter.next(); 
    String key = me.getKey().toString(); 
    me.setValue(false);  
}  
this.notifyAll(); 
return true;    

実行中、私はのsomeMethodに何をしたか

while (some condition){ 
    ObjectType obj = theSingleton.getInstance().getSharedObject(); 
    obj.SomeMethod(threadID); 
    if (obj.waitisneeded()) 
    synchronized (obj) { 
     obj.wait(); 
    } 
} 

これは私を未熟なものにした結果とデッドロック。

どうすれば修正できますか?

注:スレッドの作成方法を変更することはできません。これらのメソッドのみを変更できます。あなたはすべてのスレッドを作成したい時点で、その後

static final CyclicBarrier barrier = new CyclicBarrier(numberOfThreads); 

:あなたがスレッドの数を知っていれば(プラス待ち時間があるスレッドでwhileループは)

+0

rendezVousPointカウントが0になった)この状況で

static final CountDownLatch rendezVousPoint = new CountDownLacth(numberOfThreads); //Every thread does the following right before waiting on the rendez vous point rendezVousPoint.countDown(); rendezVousPoint.await(); 

最後のスレッドがそれらのすべてを到着すると解除されるまで、すべてのスレッドがawait()方法でブロックされます実行します。ここでは

は、あなたがこれを達成する方法でありますそれぞれが 'obj.SomeMethod()'を呼び出す前にいくつのスレッドが作成されているか知っていますか? –

+0

"予想されるすべてのスレッドが現在シングルトンと呼ばれている"時点に達したことをどのように知っていますか? –

+0

@TheScrumMeisterスクラムマイスターはい、私はスレッドの数を知っています – kenny

答えて

2

は、あなたがCyclicBarrierを使用することができます他の人を待って、あなたが呼び出す:

​​

まだその行に到着していないスレッドがあれば、await()を呼び出すスレッドがブロックされます。すべてのスレッドがそこに着くとawait()を呼び出すと、それらはすべて再開します。

同期メカニズムを構築する必要があるたびに、パッケージjava.util.concurrentを必ず確認してください。専門家によって作成された素晴らしいクラスがたくさんあります。ほとんどの場合、何かカスタムは必要ありません。同じパッケージにいくつかのクラスがあり、待ち/通知を直接使う必要はほとんどありません。メソッドを直接;あなたが見ることができるように、あなたは非常に簡単に自分自身をデッドロックにすることができます!

+0

私はCyclicBarrierに問題があると思います。なぜなら、varは静的であるからです。私のアプリケーションでは、このシナリオは数回並行して起こります! Xスレッド(言及するのを忘れていました)では、getSharedObject isが生成され、シングルトンのhashmap変数に格納されます。すべてのスレッドのグループはそれぞれのオブジェクトにアクセスします。これは私がロックを使用しようとした理由、そしてgetSharedObject自体をロックとして使用することです!私が静的を使用する場合は、getSharedObjectごとに新しい変数を作成する必要があります。 – kenny

+0

まあ、私はあなたのアプリケーションの仕組みを正確にはわかりません。私はあなたのシナリオに適応できると確信しています!全体的なアイデアは、レジュームする前にお互いに待たなければならないスレッドが、単一のサイクリックバリアを共有しなければならないということです。しかし、障壁を適切に公開してください! (つまり、CyclicBarriersが多数あるため、ConcurrentHashMapなどのインスタンスを保持するために並行コレクションを使用することをお勧めします)。 –

0

これは、Rendez-Vous(「予約」を意味するフランス語)と呼ばれる典型的なマルチスレッド状況です。基本的には、Nのスレッドには予定があります。すべてのスレッドが予定に達するまで待つべきです。 @Brunoが述べたように、CyclicBarrierオブジェクトを使用して状況を管理できます。シナリオが1回だけ実行される場合は、CountDownLatchも使用できます。

+0

私はこの(ab)の 'CountDownLatch'の使い方が気に入らないのです。あなたは 'CountDownLatch'を覆してしまい、' CyclicBarrier'(まさにこのシナリオを扱うように作られています)のように振る舞います。 'CDL.countDown()'と 'CDL.await()'というメソッドは、ほとんどの場合、 'CB.await()'のように動作しますが、目的のための2つのメソッドです通常、ワーカースレッドは 'CDL.countDown()'を呼び出し、マスタースレッドだけが 'CDL.await()'を呼び出して、すべてのワーカースレッドがタスクを終了するまでブロックします。 –

+0

@BrunoReisコメントをいただき、ありがとうございます。私はあなたにこれに同意しない傾向があります。公式のJavaドキュメンテーションによると、 'CDL.countDown()'と 'CDL.await()'を順番に実行するのに間違いはありません。 'CyclicBarrier'(ドキュメントごと)は、' CountDownLatch'の再利用可能な(設定およびリセットが可能です)バージョンです。 – GETah

関連する問題