2017-06-20 20 views
6

認証トークンを取得し、その後のWebサービス呼び出しに使用するWebサービス呼び出しがあります。 Webサービスコールを行うたびにトークンWebサービスを作成し、その後実際のWebサービスを呼び出すようになりました。静的メソッドの同期化または非同期化

トークンを取得する方法は次のとおりです。基本的にこのコードが行うことは、Webサービスを呼び出してトークンを取得し、GSONを使用してレスポンスを解析してトークンを取得することです。

public static String getAuthTicket() { 
    String authTicket = null; 
    HttpResponse httpResponse = getAuthResponse(); 
    String body; 
    if (httpResponse.getStatusLine().getStatusCode() == 200) { 
    try { 
     body = IOUtils.toString(httpResponse.getEntity().getContent()); 
     Gson gson = new GsonBuilder().disableHtmlEscaping().create(); 
     ResponseTicket responseTicket = gson.fromJson(body, ResponseTicket.class); 
     authTicket = responseTicket.getTicket(); 
    } catch (UnsupportedOperationException e) { 
     LOGGER.error("UnsupportedOperationException : ",e); 
    } catch (IOException e) { 
     LOGGER.error("IO Exception : ",e); 
    } 
    } 
    return authTicket; 
} 

これは明らかにパフォーマンスの問題につながっています。したがって、トークンを取得するためにWebサービスを提供しているパーティーはトークンを30分間有効にしました。

したがって、私たちが考えているのは、トークンを時間とともにキャッシュに入れ、現在のキャッシュ時間が30未満であるかどうかをチェックすることです。時間が30を超えると、トークンを取得し、キャッシュ内のタイムスタンプでトークンを更新します。

唯一のことは、競合状態のために不正なauthtokenを取得しないように、同期に関することが怖いです。

私は、この静的メソッドを同期化すると考えています。他に良い方法があると思いますか?

+3

2つの操作の間の競合状態? –

+0

後続のWebサービスコールを行う前にauthトークンを取得する競合条件 – noob

+0

authトークンはどこに格納/キャッシュしますか? – Markus

答えて

7

答えは:に依存します。

複数のスレッドが同じ時点で共有データにアクセスする場合、競合状態が発生します。だから、次のようなコードを持っているだろうというとき:

private final Map<X, Y> sharedCache = new HashMap<>(); 

public static getAuthTicket() { 
    if (! sharedCache.containsKey...) { 
    sharedCache.put(... 
... 

をあなたはレースの条件に従うだろう - 2つのスレッドが同時に来ることができ、非常に同時にマップを共有更新。あらゆる種類の問題につながります。

私はあなたのコードの権利を取得する場合 - あなたは似たものがあるでしょう:

private static String cachedToken = null; 

public static getAuthTicket() { 
    if (cachedToken == null || isTooOld(cachedToken)) { 
    cachedToken = getAuthTicketForReal(); 
    } 
    return cachedToken; 
} 

おそらくないは、2つのスレッドが並列にgetAuthTicketForReal()を呼び出すことをしたいですか。

したがって、その方法をに同期させると、は有効なアプローチです。

ここで、実際の質問は:それはで十分ですそのキーワードを追加するには?私のコードを考えれば、答えは「はい」です。このキャッシュが2つ以上のスレッドによって「並行」に設定されないようにするだけです。

最後に、を同期させた場合のパフォーマンスへの影響を心配している場合は、をここで忘れてください。あなたは、マルチ秒の「ネットワークベースの」操作について話しています。だから、が同期しているミリ秒のオーバーヘッドを心配する必要はありません(この数字を構成する - 重要なこと:あなたが行っている操作のコンテキストでは問題にならないほど小さいです)。あなたのコメントについて

:もちろん、同期を使用すると、JVMがその方法にの呼び出しをシリアル化することを意味します。これは、このメソッドが返すために1分かかる必要がある場合、そのメソッドへの他の呼び出しはすべてブロックその1分間です。

その意味では、 でなくでない方法でこのメソッドを書き込む方法を調べるのは良い練習かもしれませんメソッドレベルで同期します。例えば、それらを操作する複数のスレッドを処理できるデータ構造を使用します。

+0

ありがとうございます。私はこれを答えとしてマークします。私は私の教授に同期して何かにアクセスする期間は、あなたの義理の家を訪問するようなものでなければならないと私に教えさせたように、恐怖を感じました。問題を避けるためにできるだけ短くする必要があります。 – noob

関連する問題