1

スレッドの呼び出しの進行状況が 2 つの変数の状態に依存するシステムを構築しています。1 つの変数が (クライアント スレッドとは別の) 外部ソースによって散発的に更新され、両方の変数の条件で複数のクライアント スレッドがブロックされます。システムはこんな感じ

TypeB waitForB() { // Can be called by many threads.
    synchronized (B) {
        while (A <= B) { B.wait(); }
        A = B;
        return B;
    {
}

void updateB(TypeB newB) { // Called by one thread.
    synchronized (B) {
        B.update(newB);
        B.notifyAll(); // All blocked threads must receive new B.
    }
}

更新された B の新しい値を受け取るには、すべてのブロックされたスレッドが必要です。しかし、問題は、単一のスレッドが終了して A を更新すると、待機状態が再び真になり、他のスレッドの一部がブロックされ、B の新しい値を受け取らないことです。 B の更新 A でブロックされましたか、またはこの動作を取得する別の方法ですか?

4

3 に答える 3

0

私の提案は、スレッドが変更について登録するだけで新しい値について知りたいイベントベースのアプローチを使用しようとしてBいます! そして、単一のスレッドはそれらを呼び出す(トリガーする)だけです。
このようなもの。
最初にイベント サインを宣言します。

interface EventListener{
void onUpdate(TypeB oldOne,TypeB newOne);
}

次に、リスナーとして実装します。

class ManyThread implements EventListener,Runnable{
...
private TypeA a;
  synchronized void onUpdate(TypeB oldOne,TypeB newOne){
    if(!oldOne.equals(newOne)){a=newOne;this.notify();}
  }

  public ManyThread(){SingleThread.registerListener(this);}
  public synchronized void run(){
     this.wait();//waiting for an event!
     //some business
  }
...
}

次に、イベント発行者を提供します。

final class EventMgr{//would be as a singleton  guy too
  private EventMgr(){}
  static private java.util.List<EventListener> li=new java.util.ArrayList<EventListener>();
  static synchronized public void registerListener(EventListener e){li.add(e);}
  static synchronized void triggerListeners(TypeB oldOne,TypeB newOne){
    for(EventListener e:li){e.onUpdate(oldOne,newOne)}
  }
}

EventMgr男による単純なトリガーリスナー

class SingleThread{
   TypeB oldOne,B;
   void updateB(TypeB newB) { // Called by one thread.
      synchronized (B) {
        oldOne=B.clone();
        B.update(newB);
        //B.notifyAll();
        EventMgr.triggerListeners(oldOne,B);
      }
   }
}
于 2013-11-09T07:31:21.850 に答える
0

私は次のアイデアを持っています: スレッドのカウンターが B の「良い」値を待機するようにするには、最初に起動されたスレッドがその良い値をキャッシュし、その時点までの他のリーダーがそれを読み取れるようにします。以前のすべてのラウンド スレッドが完了するまで、新しいリーダーを待機ループから除外します。

コードの概要は次のとおりです。

final AtomicInteger A = new AtomicInteger(-1), B = new AtomicInteger(-1);
int cachedB = -1;

int readersCount;

int waitForB() throws InterruptedException { // Can be called by many threads.
    synchronized (B) {
        while (cachedB != -1) B.wait();

        readersCount ++;

        while (A.get() <= B.get()) { B.wait(); }

        if (cachedB == -1) {
            cachedB = B.get();
            A.set(B.get());

            readersCount--;
            if (readersCount == 0) { cachedB = -1; B.notifyAll(); }

            return B.get();
        } else {
            int ret = cachedB;

            readersCount--;
            if (readersCount == 0) { cachedB = -1; B.notifyAll(); }

            return ret;
        }
    }
}

void updateB(int newB) { // Called by one thread.
    synchronized (B) {
        B.set(newB);
        B.notifyAll(); // All blocked threads must receive new B.
    }
}
于 2013-11-09T21:04:22.490 に答える