Java Web 服务中的单例对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11096310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Singleton Object in Java Web service
提问by nick.katsip
Good morning, I am currently developing a java web application that exposes a web service interface. In order to keep a global object in memory, I use the following class as a Singleton:
早上好,我目前正在开发一个公开 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;
}
}
I am using the above class in order to have the same instance of the HashMap for all the threads of the web service. The Web service class that maintains the SingletonMap object is the following:
我正在使用上面的类,以便为 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();
}
}
The reason i have the method getCouponMapCreationTime() is to check that all the threads of the web service are accessing the same object. Is the above approach correct? How about performance overheads? Do you think I need the Singleton properties, or could I just use a static HashMap for all the threads? If I use a static HashMap, is it going to be garbage collected in case no thread is active?
我使用 getCouponMapCreationTime() 方法的原因是检查 Web 服务的所有线程是否都在访问同一个对象。上述方法是否正确?性能开销如何?你认为我需要单例属性,还是我可以只对所有线程使用静态 HashMap?如果我使用静态 HashMap,如果没有线程处于活动状态,它是否会被垃圾收集?
Thank you for your time.
感谢您的时间。
回答by ggarciao
A JAX-WS web service is by itself a Singleton. This means that all the request will be handled using a single web service instance (like a Servlet).
JAX-WS Web 服务本身就是一个单例。这意味着所有请求都将使用单个 Web 服务实例(如 Servlet)进行处理。
So, any member of the class will be 'shared' between all the request. In your case, you do not need to make your members (i.e. couponMap) an static attributes.
因此,该类的任何成员都将在所有请求之间“共享”。在你的情况下,你不需要让你的成员(即couponMap)成为一个静态属性。
Conclusion:Don't worry, all your threads (request) will be accessing the same 'couponMap'. Because you don't need the getCouponMapCreationTime
anymore, I think that you can eliminate the SingletonMap
abstraction and use directly a Map in your web service class.
结论:别担心,您的所有线程(请求)都将访问同一个“couponMap”。因为您不再需要getCouponMapCreationTime
了,我认为您可以消除SingletonMap
抽象并直接在您的 Web 服务类中使用 Map。
But I have something very important to add. If several threads (request) will be accessing your Map you have to make it thread-safe!!! There are a lot of way to do this, but I will give an idea: Use a ConcurrentHashMap
instead of a HashMap
. This will make all your get(), put(), remove()
operations thread-safe! If you need a larger scope you can use synchronized blocks, but please avoid synchronize methods because the scoop is too large and always synchronize over this
object.
但是我要补充一些非常重要的东西。如果多个线程(请求)将访问您的地图,您必须使其成为线程安全的!!!有很多方法可以做到这一点,但我会给出一个想法:使用 aConcurrentHashMap
而不是 a HashMap
。这将使您的所有get(), put(), remove()
操作都是线程安全的!如果你需要更大的范围,你可以使用同步块,但请避免同步方法,因为勺子太大并且总是在this
对象上同步。
回答by artbristol
JAX-WS has its own patterns for creating singletons, you don't need to use static fields. You use the @Inject
annotation into each service. See this blog post: http://weblogs.java.net/blog/jitu/archive/2010/02/19/jax-ws-cdi-java-ee-6-0(but don't use @SessionScoped
, use @Singleton
)
JAX-WS 有自己的创建单例的模式,您不需要使用静态字段。您在@Inject
每个服务中使用注释。请参阅此博客文章:http: //weblogs.java.net/blog/jitu/archive/2010/02/19/jax-ws-cdi-java-ee-6-0(但不要使用@SessionScoped
,使用@Singleton
)
Some other points:
其他一些要点:
HashMap
isn't thread-safe, you needConcurrentHashMap
.This
catch(NamingException e) { System.err.println(e.getMessage());
is unhelpful. Rethrow it as aRuntimeException
. You can't recover from it.Don't worry about performance overhead at this stage. Measure it once you have something working.
HashMap
不是线程安全的,你需要ConcurrentHashMap
.这
catch(NamingException e) { System.err.println(e.getMessage());
是无益的。将其作为RuntimeException
. 你无法从中恢复。在这个阶段不要担心性能开销。一旦你有一些工作,就测量它。