阻塞当前线程的执行,直到另一个线程更新变量。

3

我的代码:

    private  AtomicBoolean fetched1 = new AtomicBoolean(false);

    private int  rowCount;

    public int getRowCount() {
            data.getRealm().exec(new Runnable(){
                @Override
                public  void run() {
                    rowCount = data.size();
                    fetched1.set(true);
                }
            });
            while(!fetched1.get()){
            }
            fetched1.set(false);
            return rowCount;
        }

现在看起来对我有用,但是我不熟悉线程(它总是让我感到困惑),我是否应该按照上面的代码进行操作?

2个回答

8
我应该按照上面的代码方式来做吗?这似乎是一个旋转循环,会浪费不必要的CPU。最好使用“wait”和“notify”来通知数据已被获取。类似这样:
   private final Object lock = new Object();
   private volatile Integer rowCount = null;
   ...

      public void run() {
         rowCount = data.size();
         synchronized (lock) {
            lock.notify();
         }
      }

  synchronized (lock) {
     // we loop here in case of race conditions or spurious interrupts
     while (rowCount == null) {
        lock.wait();
     }
  }
  ...

我认为你根本不需要获取AtomicBoolean。你应该将rowCount设置为volatile,然后可以测试其值。使用while循环是一个很好的模式,因为涉及到生产者和消费者竞争条件以及虚假中断。


我认为你忘记添加fetched.set(true);了。 - Peter Lawrey
是的,谢谢@Peter。我完全不需要使用fetched了。 - Gray
我会将已更新/已检查字段移至同步块中。在这种情况下,虽然很简单,但在更复杂的情况下会需要它。 - Peter Lawrey
使用负的 rowCount 有点丑陋,因为您正在违反问题的隐式不变量。使用单独的布尔值指示行已更新会更好吧? - Tudor
1
@CaiNiaoCoder 这没有关系。它必须无论如何都能正常工作。一般来说,已经运行的线程将首先到达该块,其他线程必须启动。 - Peter Lawrey
显示剩余6条评论

4

你有两个问题

  • 第一个线程正在忙等待,通常是不可取的。
  • 该模式无法扩展到更多线程,因为第二个线程可能会尝试将值设置为true。

相反,最简单的模式是锁定对象,并在值改变时等待/通知。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接