0

我有一个线程问题..

我正在使用内部类进行查找..我一直在阅读如何正确执行此操作,并且所有内容都指向使用字段..在我的情况下是“布尔验证”。

基本上如果对象在那里。我将字段声明为 true 并返回值。问题是,在性能测试期间,同一对象中的同一方法同时在多个线程中被调用,并且效果很有趣。(我猜是因为 pause() (等待 10 毫秒))

所以在线程A..那里的对象,所以它声明字段true..waits 10ms..在线程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如果对象由多个线程共享,则创建字段将不起作用。

您可以使用的一个选项是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 回答