Java Web服务中的Singleton对象

时间:2012-06-19 07:28:52

标签: java singleton jax-ws

早上好, 我目前正在开发一个公开Web服务接口的Java Web应用程序。为了将全局对象保留在内存中,我将以下类用作Singleton:

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,如果没有线程处于活动状态,它是否会被垃圾收集?

感谢您的时间。

2 个答案:

答案 0 :(得分:7)

JAX-WS Web服务本身就是一个Singleton。这意味着将使用单个Web服务实例(如Servlet)处理所有请求。

因此,该类的任何成员都将在所有请求之间“共享”。在您的情况下,您不需要使您的成员(即couponMap)成为静态属性。

结论:别担心,您的所有主题(请求)都将访问相同的“couponMap”。因为您不再需要getCouponMapCreationTime,我认为您可以消除SingletonMap抽象并直接在Web服务类中使用Map。

但我有一些非常重要的补充。如果几个线程(请求)将访问您的地图,您必须使其线程安全!有很多方法可以做到这一点,但我会提出一个想法:使用ConcurrentHashMap代替HashMap。这将使您的所有get(), put(), remove()操作都是线程安全的!如果您需要更大的范围,则可以使用synchronized块,但请避免使用同步方法,因为scoop太大并且始终在this对象上进行同步。

答案 1 :(得分:3)

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. 在此阶段不要担心性能开销。有一些工作后测量它。