我希望这将是足够的信息,所以在这里。如果您需要更多信息,请在评论中了解。
我有一个有两个内部类的类。内部类每个都有两个方法来调用外部类中的方法。所以,它看起来像这样:
public OuterClass {
private boolean outerMethodHasBeenCalled = false;
private void outerMethod() {
if(!outerMethodHasBeenCalled) {
// do stuff
}
outerMethodHasBeenCalled = true;
}
private FirstInnerClass {
public void someMethod() {
outerMethod();
}
}
private SecondInnerClass {
public void someOtherMethod() {
outerMethod();
}
}
}
重要的是要注意:
FirstInnerClass
和SecondInnerClass
的实例作为JavaScript界面传递给WebView,因此可以随时调用someMethod
和someOtherMethod
,无需特定顺序。outerMethod
几乎在同一时间被调用(我打印出一条日志消息,并且它们被加上时间戳到1000的第二个)由不同的对象。我的应用程序然后'做东西'两次,因为outerMethodHasBeenCalled
在调用outerMethod
时仍然是假的。这不好,这正是我想要阻止的。我的应用只应该只做一次“做东西”:第一次调用outerMethod
。OuterClass
的多个实例,但请放心,它只是OuterClass
的一个实例。 重要的是我的应用程序'只在第一次outerMethod
被调用时才会“填充”(我希望现在这一点很明显)。所有后续调用基本上都被忽略。无论哪个内部类首先调用outerMethod
- 都无关紧要。
那么,在这种情况下使用synchronized关键字是否合适?
答案 0 :(得分:19)
private synchronized void outerMethod() {
...
}
注意,这会产生阻塞其中一个调用者的副作用,直到outerMethod()完成。如果这是可以接受的,很酷。如果意图仅仅是outerMethod()中的代码运行一次,和,如果第一个调用者正在运行outerMethod(),则第二个调用者不会被延迟,你可以考虑:< / p>
public OuterClass {
private AtomicBoolean outerMethodHasBeenCalled = new AtomicBoolean();
private void outerMethod() {
if (outerMethodHasBeenCalled.compareAndSet(false, true)) {
// do stuff
}
}
...
请参阅JavaDoc for AtomicBoolean以了解其中发生的事情(假设它在Android的Java中可用)。
答案 1 :(得分:7)
将outerMethod
中要在同步块中仅运行一次的所有内容包裹起来:
private void outerMethod() {
synchronized (this) {
if(!outerMethodHasBeenCalled) {
// do stuff
}
outerMethodHasBeenCalled = true;
}
}
这样,第一次调用该方法时,一次只允许一个线程进入同步块。第一个将执行if语句中的代码,然后将outerMethodHasBeenCalled
设置为true
。其他线程将看到它是真的,并跳过if代码。