![](/img/trans.png)
[英]When should I use a synchronized method and when a synchronized block in Java?
[英]When to use synchronized in Java
我希望这将是足够的信息,所以在这里。 如果您需要更多信息,请在评论中了解。
我有一个有两个内部类的类。 内部类每个都有两个方法来调用外部类中的方法。 所以,它看起来像这样:
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关键字是否合适?
是的,鉴于你上面列出的内容,我会选择:
private synchronized void outerMethod() {
...
}
注意,这将产生阻止其中一个调用者的副作用,直到outerMethod()完成。 如果这是可以接受的,很酷。 如果意图仅仅是outerMethod()中的代码运行一次, 并且如果第一个调用者运行outerMethod(),则第二个调用者没有延迟是可以的,您可以考虑:
public OuterClass {
private AtomicBoolean outerMethodHasBeenCalled = new AtomicBoolean();
private void outerMethod() {
if (outerMethodHasBeenCalled.compareAndSet(false, true)) {
// do stuff
}
}
...
请参阅JavaDoc for AtomicBoolean以了解其中发生的事情(假设它在Android的Java中可用)。
将您想在同步块中只运行一次的outerMethod
中的所有内容包装:
private void outerMethod() {
synchronized (this) {
if(!outerMethodHasBeenCalled) {
// do stuff
}
outerMethodHasBeenCalled = true;
}
}
这样,第一次调用该方法时,一次只允许一个线程进入同步块。 第一个将在if语句中执行代码,然后将outerMethodHasBeenCalled
设置为true
。 其他线程将看到它是真的,并跳过if代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.