Java EE 应用程序中的线程需要担心多少?
How much to worry about threading in Java EE applications?
我有一个 Java EE 网络应用程序,其中包含一些 servlet、JSP(也是 servlet,对吗?)、SOAP 网络服务(还是 servlet?)和 REST 网络服务(也许……servlet?) .
我的问题是:我需要为多线程担心多少?我自己并没有明确地创建线程,而是让容器来操心这个。
例如,如果我有一个 JAXB 上下文的缓存(静态映射)用于某些 类 以加快编组和解组速度,我是否必须同步对它的访问?
而且我还维护了一个缓存(又是静态映射),其中包含反复使用的基本 XSLT 模板,同样的问题?
如果您的 servlet 或类似服务仅对您的共享资源使用读取操作,例如Map#get(someKey)
那就不用担心了。
如果 servlet 或类似程序中有一个进程可以改变共享资源的状态,例如Map#put(someKey, someValue)
而其他资源可能正在使用读取操作,那么是的,您应该使用同步或使用 ConcurrentHashMap
.
除此之外,请确保存储在缓存中的对象的状态不能被客户端更改,以避免应用程序中出现其他问题。请注意,这些问题(可能)不会引发 ConcurrentModificationException
但您会注意到其影响。
我只是想在这里添加一个答案。
正如您所暗示的那样,在 java 中,如果它支持 HTTP,那么当您开始使用它时,很可能是某种 servlet 是的。
而且只要你遵守规则,你就不必担心多线程在负载或死锁等方面的问题。
正如其他人指出的那样,Servlet 在请求之间共享。如果您将包含 'state'(servlet 中的成员变量)的任何内容放入其中,它将被共享,因此可以被并发访问。
您的地图绝对是其中之一。
我建议您查看 EHCache,它是一个 'in memory' 缓存解决方案,非常适合您的目的。在使用时,它就像一张地图。
Element element = new Element("key1", "value1");
cache.put(element);
但是它管理着你放入其中的对象的整个生命周期,它什么时候过期等等。它还为你处理并发。也就是我平时所说的'automagic'.
EHCache 的最大优点是您还可以使用它来扩展您的应用程序。您可以 运行 一个相同的服务器,使用循环负载平衡器 (apache) 来选择哪个服务器获得下一个请求,并在实例之间共享缓存。 EHCache 正在失去对其他缓存机制的支持,但在我看来,它仍然是迄今为止最好的解决方案。它非常适合您的目的。 (我不为兵马俑工作!)
如果您不需要像 EHCache 这样的整个库/框架的重量级功能,您可以使用现有/提供的 JavaEE API 非常轻松地确保线程安全。只需创建一个 @Singleton
EJB(参见 link 下面的示例 ),它使用容器管理的并发来管理您的 Map 访问并注入(使用 @EJB
) 将此 EJB 添加到您的 Servlet 或 JAX-RS 资源中。如果您需要注入 JSP,您可以编写一个小的实用方法来查找 EJB,因为注入注释在 JSP 中不起作用。
我有一个 Java EE 网络应用程序,其中包含一些 servlet、JSP(也是 servlet,对吗?)、SOAP 网络服务(还是 servlet?)和 REST 网络服务(也许……servlet?) .
我的问题是:我需要为多线程担心多少?我自己并没有明确地创建线程,而是让容器来操心这个。
例如,如果我有一个 JAXB 上下文的缓存(静态映射)用于某些 类 以加快编组和解组速度,我是否必须同步对它的访问?
而且我还维护了一个缓存(又是静态映射),其中包含反复使用的基本 XSLT 模板,同样的问题?
如果您的 servlet 或类似服务仅对您的共享资源使用读取操作,例如Map#get(someKey)
那就不用担心了。
如果 servlet 或类似程序中有一个进程可以改变共享资源的状态,例如Map#put(someKey, someValue)
而其他资源可能正在使用读取操作,那么是的,您应该使用同步或使用 ConcurrentHashMap
.
除此之外,请确保存储在缓存中的对象的状态不能被客户端更改,以避免应用程序中出现其他问题。请注意,这些问题(可能)不会引发 ConcurrentModificationException
但您会注意到其影响。
我只是想在这里添加一个答案。 正如您所暗示的那样,在 java 中,如果它支持 HTTP,那么当您开始使用它时,很可能是某种 servlet 是的。
而且只要你遵守规则,你就不必担心多线程在负载或死锁等方面的问题。 正如其他人指出的那样,Servlet 在请求之间共享。如果您将包含 'state'(servlet 中的成员变量)的任何内容放入其中,它将被共享,因此可以被并发访问。 您的地图绝对是其中之一。
我建议您查看 EHCache,它是一个 'in memory' 缓存解决方案,非常适合您的目的。在使用时,它就像一张地图。
Element element = new Element("key1", "value1");
cache.put(element);
但是它管理着你放入其中的对象的整个生命周期,它什么时候过期等等。它还为你处理并发。也就是我平时所说的'automagic'.
EHCache 的最大优点是您还可以使用它来扩展您的应用程序。您可以 运行 一个相同的服务器,使用循环负载平衡器 (apache) 来选择哪个服务器获得下一个请求,并在实例之间共享缓存。 EHCache 正在失去对其他缓存机制的支持,但在我看来,它仍然是迄今为止最好的解决方案。它非常适合您的目的。 (我不为兵马俑工作!)
如果您不需要像 EHCache 这样的整个库/框架的重量级功能,您可以使用现有/提供的 JavaEE API 非常轻松地确保线程安全。只需创建一个 @Singleton
EJB(参见 link 下面的示例 ),它使用容器管理的并发来管理您的 Map 访问并注入(使用 @EJB
) 将此 EJB 添加到您的 Servlet 或 JAX-RS 资源中。如果您需要注入 JSP,您可以编写一个小的实用方法来查找 EJB,因为注入注释在 JSP 中不起作用。