0

我有一个简单的问题:

Class A{

    B b;

    public void doSth{ 
         //This method should execute only once
         b.modify(); //calls doSth() again...
    }
}

当程序运行时,A 的一个实例被传递给 B,B 调用 doSth(例如作为回调)。b.modify让 BA.doSth()再次调用,这将是无限的调用序列。我想要实现的是:我想执行一次 doSth(),修改 B,然后在下次执行时以某种方式停止无限调用链并且不执行b.modify

任何建议都非常感谢。

4

8 回答 8

8

为您的班级添加州旗:

Class A {

    B b;
    private volatile boolean called;

    public synchronized void doSth { 
         if (called) return;
         called = true;
         b.modify();
    }
}

volatile如果有多个线程在使用,请使用。

于 2012-08-06T13:05:24.360 回答
2

您可以有一个布尔字段,并在您第一次调用该方法时将其设置为 true。

Class A{
    boolean isModified = false;
    B b;

    public void doSth{ 
        if(!isModified) {
            this.isModified = true;
            b.modify();
        }
    }
}
于 2012-08-06T13:05:12.430 回答
2

我会尝试找到一个不涉及循环依赖的解决方案。A和B真的必须互相引用吗?在更高的层次上,你想要达到什么目标?您可以使用 A 和 B 对象发布一些客户端代码吗?

于 2012-08-06T13:07:10.687 回答
1

在类 A 中添加 aboolean alreadyExecuted并将 doSmth() 的实现修改为

 public void doSth{ 
     if(!alreadyExecuted){
         alreadyExecuted = true; 
         b.modify(); 

     }
}
于 2012-08-06T13:05:41.727 回答
1

这是对“最佳”示例的修复,因为没有人应该在并发/多线程情况下真正使用它。您可以让两个线程都运行“如果”,并且都将传递到下一行。最好在这里使用 CAS,例如:

私有最终 AtomicBoolean 调用 = new AtomicBoolean();

接着

如果 (!call.compareAndSet(false, true)) 返回;

或者如果您更喜欢使用“plain and pure”风格,请使用带同步的双重检查:

调用私有 volatile 布尔值;

接着

boolean mayPass = false;
如果(!调用){
  synchronized(this) { // 或一些外部对象
    如果(!调用){
      称为=真;
      可能通过=真;
    }
  }
}
if (!mayPass) 返回;
...
于 2013-12-12T17:18:15.327 回答
1

也许您应该更改设计以不递归调用这些方法,或者如果您不能只将参数添加到您的 doSth 方法

doSth(boolean modify)
 {
  if (modify) 
  {
    b.modify();
  }
  ...
 }
于 2012-08-06T13:15:44.783 回答
1

将其视为黑客...

使用boolean变量

Class A{

    B b;
    public isOk = true;

    public void doSth{ 

        if (isOk){

         b.modify(); 
         isOk = false;

        }

}
于 2012-08-06T13:07:53.197 回答
0

把你的工作放在构造函数中

Class A{

   B b;

   A(){
       //This should execute only once
       b.modify(); //calls doSth() again...
   }

}
于 2012-08-06T13:40:22.227 回答