7

おはようございます。私は現在、Web サービス インターフェイスを公開する Java Web アプリケーションを開発しています。グローバル オブジェクトをメモリに保持するために、次のクラスをシングルトンとして使用します。

public class SingletonMap {
    private static final SingletonMap instance = new SingletonMap();
    private static HashMap couponMap = null;
    private static long creationTime;

    private SingletonMap() {
        creationTime = System.currentTimeMillis();
        couponMap = new HashMap();
    }

    public static synchronized SingletonMap getInstance() {
        return instance;
    }

    public static long getCreationTime() {
        return creationTime;
    }
}

Web サービスのすべてのスレッドに対して HashMap の同じインスタンスを作成するために、上記のクラスを使用しています。SingletonMap オブジェクトを維持する Web サービス クラスは次のとおりです。

@WebService()
public class ETL_WS {
    private String TOMCAT_TEMP_DIR;
    private final int BUFFER_SIZE = 10000000;
    private static SingletonMap couponMap;
    private static SingletonProductMap productCategoryMap;
    private String dbTable = "user_preferences";

    public ETL_WS() {
        Context context = null;
        try {
            context = (Context) new InitialContext().lookup("java:comp/env");
            this.TOMCAT_TEMP_DIR = (String) context.lookup("FILE_UPLOAD_TEMP_DIR");
        }catch(NamingException e) {
        System.err.println(e.getMessage());
    }

    public long getCouponMapCreationTime() {
        return couponMap.getCreationTime();
    }

}

メソッド getCouponMapCreationTime() を使用する理由は、Web サービスのすべてのスレッドが同じオブジェクトにアクセスしていることを確認するためです。上記のアプローチは正しいですか?パフォーマンスのオーバーヘッドはどうですか? Singleton プロパティが必要だと思いますか、それともすべてのスレッドに静的な HashMap を使用できますか? 静的な HashMap を使用すると、アクティブなスレッドがない場合にガベージ コレクションが行われますか?

お時間をいただきありがとうございます。

4

2 に答える 2

11

JAX-WSWebサービスはそれ自体がシングルトンです。これは、すべてのリクエストが単一のWebサービスインスタンス(サーブレットなど)を使用して処理されることを意味します。

したがって、クラスのすべてのメンバーは、すべてのリクエスト間で「共有」されます。あなたの場合、メンバー(つまりcouponMap)を静的属性にする必要はありません。

結論:心配しないでください。すべてのスレッド(リクエスト)が同じ「couponMap」にアクセスします。もう必要ないので、抽象化をgetCouponMapCreationTime排除して、Webサービスクラスで直接マップを使用できると思います。SingletonMap

しかし、追加することが非常に重要です。複数のスレッド(リクエスト)がマップにアクセスする場合は、スレッドセーフにする必要があります!!! これを行う方法はたくさんありますが、私はアイデアを与えます:のConcurrentHashMap代わりにを使用してくださいHashMap。これにより、すべてのget(), put(), remove()操作がスレッドセーフになります。より大きなスコープが必要な場合は、同期ブロックを使用できますが、スクープが大きすぎて常にthisオブジェクトを介して同期するため、同期メソッドは避けてください。

于 2012-06-19T07:52:10.023 に答える
4

JAX-WS にはシングルトンを作成するための独自のパターンがあるため、静的フィールドを使用する必要はありません。@Inject各サービスにアノテーションを使用します。次のブログ投稿を参照してください: http://weblogs.java.net/blog/jitu/archive/2010/02/19/jax-ws-cdi-java-ee-6-0@SessionScoped (ただし、 を使用しないでください@Singleton)

その他のポイント:

  1. HashMapはスレッドセーフではありません。必要ConcurrentHashMapです。

  2. これcatch(NamingException e) { System.err.println(e.getMessage());は役に立ちません。として再スローしRuntimeExceptionます。そこから回復することはできません。

  3. この段階では、パフォーマンスのオーバーヘッドについて心配する必要はありません。何かが機能したら、それを測定します。

于 2012-06-19T07:47:07.220 に答える