Javaの同時実行性:Webサービスへのアクセスをスレッドセーフにする
-
10-07-2019 - |
質問
Axis2 Webサービスで並行性を処理するための正しい/最良の方法を知りたい。
たとえば、次のコードが与えられた場合:
public class MyServiceDelegate
{
@Resource
UserWebService service; // Injected by spring
public CustomerDTO getCustomer()
{
String sessionString = getSessionStringFromCookies();
service.setJSESSIONID(sessionString);
CustomerDTO customer = service.getCustomerFromSessionID();
}
}
上記では、UserWebServiceはサードパーティAPIであることに注意してください。このサービスでは、呼び出しを行うときに、認証済みセッションの JSESSIONID
でCookieを渡す必要があります。
この文はスレッドセーフではないと仮定して訂正しますか? IE。、2つのスレッドが与えられた場合、以下が発生する可能性はありますか?
- ThreadA:
service.setJSESSIONID(" threadA")
- ThreadB:
service.setJSESSIONID(" threadB")
- ThreadA:
service.getCustomerFromSessionID // service.sesionID ==" threadB"
もしそうなら、この状況に対処する最も適切な方法は何ですか?サービスにリソースプールを使用する必要がありますか?または、サービスを同期済みとして宣言する必要がありますか?
public CustomerDTO getCustomer()
{
synchronized( service ) {
service.setJSESSIONID(sessionString);
CustomerDTO customer = service.getCustomerFromSessionID();
}
}
または、この問題を処理する別の、より適切な方法はありますか?
解決
各スレッドに独自のDelegateオブジェクトがあるため、独自のUserWebServiceサービスがありますか?
単純な場合、スタックでデリゲートが作成された場合、スレッドは独立します。
作成のコストが高い場合は、デリゲートオブジェクトのプールを用意します。プールから1つを取るのは、比較的安価です。ハウスキーピングには細心の注意を払う必要がありますが、事実上、これはデータベース接続で行われます。一部の環境には、このようなプーリングを管理するためのユーティリティクラスがあります-独自にロールするよりも好ましい傾向があります。
他のヒント
UserWebServiceはクラスの1つですか?もしそうなら、メソッドのシグネチャを次のように変更すると思います:
public CustomerDTO getCustomer()
{
CustomerDTO customer = service.getCustomerFromSessionID(sessionString);
}
また、UserWebServiceに状態を維持させないでください。そうすれば、本質的にスレッドセーフになります
おっしゃるように、この関数はスレッドセーフではありません。 Javaにはモニターを作成する簡単な方法があります。これは、一度に1つのスレッドのみが関数にアクセスできるようにするオブジェクトです。 モニター
の詳細スレッドセーフにするには、同期を式の周り、または関数名の前に追加します:
public synchronized CustomerDTO getCustomer(){
service.setJSESSIONID(sessionString);
CustomerDTO customer = service.getCustomerFromSessionID();
}
2つの違いは、どのオブジェクトをモニターに変えるかです。