我有一个简单的问题:
Class A{
B b;
public void doSth{
//This method should execute only once
b.modify(); //calls doSth() again...
}
}
程序运行时,A的实例传递给B,B调用doSth(例如作为回调)。 b.modify
让B再次呼叫A.doSth()
,这将是无限的呼叫序列。我想要实现的是:我想执行一次doSth(),修改B,然后在下次执行时以某种方式停止无限调用链并且不执行b.modify
。
任何建议都非常感谢。
答案 0 :(得分:7)
向您的班级添加州旗:
Class A {
B b;
private volatile boolean called;
public synchronized void doSth {
if (called) return;
called = true;
b.modify();
}
}
如果正在播放多个主题,请使用volatile
。
答案 1 :(得分:2)
您可以拥有一个布尔字段,并在第一次调用该方法时将其设置为true。
Class A{
boolean isModified = false;
B b;
public void doSth{
if(!isModified) {
this.isModified = true;
b.modify();
}
}
}
答案 2 :(得分:2)
我试图找到一个不涉及循环依赖的解决方案。 A和B真的要互相参考吗?在更高的层面上,你想要实现什么?你能用A和B对象发布一些客户端代码吗?
答案 3 :(得分:1)
向A类添加boolean alreadyExecuted
并将doSmth()的实现修改为
public void doSth{
if(!alreadyExecuted){
alreadyExecuted = true;
b.modify();
}
}
答案 4 :(得分:1)
将此视为黑客...
使用boolean
变量
Class A{
B b;
public isOk = true;
public void doSth{
if (isOk){
b.modify();
isOk = false;
}
}
答案 5 :(得分:1)
也许你应该改变设计,不要递归地调用这些方法,或者你不能只是在你的doSth方法中添加参数
doSth(boolean modify)
{
if (modify)
{
b.modify();
}
...
}
答案 6 :(得分:1)
这是对“最佳”示例的修复,因为没有人应该在并发/多线程情况下使用它。您可以让两个线程都运行“if”,并且两个线程都将传递到下一行。 最好在这里使用CAS,例如:
private final AtomicBoolean called = new AtomicBoolean(); and then if (!called.compareAndSet(false, true)) return;
或者如果您更喜欢使用“普通和纯粹”样式,请使用带有synchronized的双重检查:
private volatile boolean called; and then boolean mayPass = false; if (!called) { synchronized(this) { // or some external object if (!called) { called = true; mayPass = true; } } } if (!mayPass) return; ...
答案 7 :(得分:0)
将你的工作放在构造函数中
Class A{
B b;
A(){
//This should execute only once
b.modify(); //calls doSth() again...
}
}