質問
Webアプリにclass" Foo"というクラスがあるとします。 Springを使用してBeanが作成されるときに呼び出されるinitialise()メソッドがあります。次に、initialise()メソッドは外部サービスをロードし、それをフィールドに割り当てようとします。サービスに接続できなかった場合、フィールドはnullに設定されます。
private Service service;
public void initialise() {
// load external service
// set field to the loaded service if contacted
// set to field to null if service could not be contacted
}
クラス" Foo"でget()メソッドを呼び出すと、 initialise()メソッドで開始されたサービスは呼び出されます。サービスのフィールドがnullの場合、外部サービスをロードしてみます。
public String get() {
if (service == null) {
// try and load the service again
}
// perform operation on the service is service is not null
}
このようなことをすると、同期の問題が発生する可能性がありますか?
解決
toolkit の答えは正しいです。問題を解決するには、同期するFooのinitialise()メソッドを宣言するだけです。 Fooを次のようにリファクタリングできます。
private Service service;
public synchronized void initialise() {
if (service == null) {
// load external service
// set field to the loaded service if contacted
}
}
public String get() {
if (service == null) {
initialise(); // try and load the service again
}
// perform operation on the service is service is not null
}
他のヒント
はい、同期の問題が発生します。
単一のサーブレットがあると仮定します:
public class FooServlet extends HttpServlet {
private MyBean myBean;
public void init() {
myBean = (MyBean) WebApplicationContextUtils.
getRequiredWebApplicationContext(getServletContext()).getBean("myBean");
}
public void doGet(HttpRequest request, HttpResponse response) {
String string = myBean.get();
....
}
}
class MyBean {
public String get() {
if (service == null) {
// try and load the service again
}
// perform operation on the service is service is not null
}
}
そして、あなたのbean定義は次のようになります:
<bean id="myBean" class="com.foo.MyBean" init-method="initialise" />
問題は、サーブレットインスタンスが複数のリクエストスレッドによって使用されることです。したがって、service == nullで保護されたコードブロックは、複数のスレッドによって入力される場合があります。
最適な修正(二重チェックロックなどを回避)は次のとおりです。
class MyBean {
public synchronized String get() {
if (service == null) {
// try and load the service again
}
// perform operation on the service is service is not null
}
}
これが理にかなっていることを願っています。そうでない場合はコメントをドロップします。
所属していません StackOverflow