0

スレッドに問題があります..

私は内部クラスを使用してルックアップを行っています..これを適切に行う方法について読んでおり、すべてがフィールドの使用を指しています..私の場合は「ブール検証」です。

基本的にオブジェクトがそこにある場合。フィールドを true と宣言し、値を返します。問題は、パフォーマンス テスト中に、同じオブジェクトの同じメソッドが複数のスレッドで同時に呼び出され、その結果がおかしくなることです。(私はpause()(10ミリ秒待つ)のために推測しています)

したがって、スレッドA..そこにオブジェクトがあるため、フィールドをtrueと宣言します..10ミリ秒待機します..スレッドBでは、オブジェクトはそこにありませんが、待機のため、同じフィールドがアクセスされているため、とにかくtrueを返します。

ここで困っています:(

これを行うためのより良い方法を知っている人はいますか?

boolean verify; 
  public boolean lookupAndVerify(String id) throws InterruptedException
  {
    final String key = id;
    PastryIdFactory localFactory = new rice.pastry.commonapi.PastryIdFactory(env);
    final Id lookupKey = localFactory.buildId(key);
    Past p = (Past) apps.get(env.getRandomSource().nextInt(apps.size()));
    p.lookup(lookupKey, new Continuation<PastContent, Exception>()
    {
      public void receiveResult(PastContent result)
      {
        P2PPKIContent content = (P2PPKIContent) result;
        if(content !=null){
        verify = true; 
        }
      }
      public void receiveException(Exception result)
      {
        System.out.println("Error looking up " + lookupKey);
      }
    });
    pause();
    return verify;
  }
4

2 に答える 2

2

非同期呼び出しについて少し調べてみるとよいと思います。特定のミリ秒数の一時停止は、コールバックが呼び出されたことを確認する安全な方法ではありませんverify。また、オブジェクトが複数のスレッドで共有されている場合、フィールドの作成は機能しません。

使用できる1つのオプションは次のとおりですFuture<Boolean>(この場合、SettableFuture<Boolean>Guavaライブラリからが便利です):

final SettableFuture<Boolean> verify = new SettableFuture<Boolean>();

p.lookup(lookupKey, new Continuation<PastContent, Exception>()
{
  public void receiveResult(PastContent result)
  {
    P2PPKIContent content = (P2PPKIContent) result;
    if(content !=null){
       verify.set(true);
    }
  }
  public void receiveException(Exception result)
  {
    System.out.println("Error looking up " + lookupKey);
    verify.set(false);
  }
});

return verificationQueue.get(); //this will block until verify has been set!

Aは、将来のある時点でFuture<T>値を持つ同時実行構造です。ただし、その値を要求するとすぐに、値が得られるまでブロックされます。

編集

何らかの理由で Guava を取り込むことができない場合、少し直感的でない解決策はBlockingQueue<Boolean>、容量が 1 の a を使用することです。

final BlockingQueue<Boolean> verificationQueue = new ArrayBlockingQueue<Boolean>(1);

p.lookup(lookupKey, new Continuation<PastContent, Exception>()
{
  public void receiveResult(PastContent result)
  {
    P2PPKIContent content = (P2PPKIContent) result;
    if(content !=null){
       verificationQueue.put(true);
    }
  }
  public void receiveException(Exception result)
  {
    System.out.println("Error looking up " + lookupKey);
    verificationQueue.put(false);
  }
});

return verify.take(); //blocks until an item has been put on the queue

これを行う場合は、より読みやすい API を使用してキューをクラスにカプセル化する価値があります。

于 2012-07-25T13:06:45.873 に答える
0

共有する必要がない場合は、スレッドごとにこれらのオブジェクトのいずれかを作成する必要があります (クラス名は省略されているため、具体的には言えません) 。

于 2012-07-25T13:06:53.970 に答える