Java:在HttpSession中保留对ArrayList的软引用有任何问题/负面影响吗?

Java:在HttpSession中保留对ArrayList的软引用有任何问题/负面影响吗?,java,httpsession,soft-references,Java,Httpsession,Soft References,我的代码正在执行以下操作(作为示例,我指定java.lang.ref.SoftReference的包路径的原因是要注意它不是我自己的实现:-): 。。。 List someData=new ArrayList(); 添加(“值1”); 添加(“价值2”); ... java.lang.ref.SoftReference softRef=新的SoftReference(someData); ... HttpSession session=request.getSession(true); setA

我的代码正在执行以下操作(作为示例,我指定java.lang.ref.SoftReference的包路径的原因是要注意它不是我自己的实现:-):

。。。
List someData=new ArrayList();
添加(“值1”);
添加(“价值2”);
...
java.lang.ref.SoftReference softRef=新的SoftReference(someData);
...
HttpSession session=request.getSession(true);
setAttribute(“mySoftRefData”,softRef);
...
后来:

...
java.lang.ref.SoftReference softRef = session.getAttribute("mySoftRefData");
if (softRef != null && softRef.get() != null) {
   List<String> someData = (List<String>)softRef.get();
   // do something with it.
}
...
。。。
java.lang.ref.SoftReference softRef=session.getAttribute(“mySoftRefData”);
if(softRef!=null&&softRef.get()!=null){
List someData=(List)softRef.get();
//用它做点什么。
}
...

有什么缺点吗?我没有看到?谢谢大家!

明显的缺点是该列表可能会不可预测地消失。由于会话在过期后会被垃圾收集,因此我没有看到SoftReference的使用案例。如果列表变得相当大(至少足以证明使用SoftReference是合理的),我建议使用不同的存储(DB、临时文件)。

将应用程序不需要的数据放入一次性缓存是一个非常好的主意。在高峰时段,它们将被丢弃,为更紧迫的需求节省更多资源


简而言之,这是一个好办法。

如果您自己没有在代码中的任何其他地方引用它,并且JVM已经运行了垃圾收集器,那么您可能会面临引用不再出现在会话中的风险。然而,这种可能性很小,比使用弱引用时要小,但仍然存在


我不会在Web应用程序中这样做。如果它是纯会话范围的数据(例如,登录用户、购物车等),则只需以正常方式将其放入会话范围。如果会话过期或无效,则任何未在其他地方引用的内容都将以任何方式进行垃圾收集。会话作用域无意充当“软”缓存。或者,如果它实际上是请求范围内的数据,则将其存储在请求范围内。否则使用另一种数据存储。

我不会直接调用会话范围的缓存。没错,Vladimir,它只是应用程序的一部分。用户可以保持登录应用程序,保持会话活动,但不使用应用程序的此特定部分。因此,对于许多用户,我们允许GC避免出现内存问题。此外,正如我前面提到的,还有另一个存储,其中存储的是实际列表。如果我得到null—不是什么大问题,只是从存储器中加载它。@sfussenger—我很想知道为什么。这并不是说我坚持自己的解决方案——我总是乐于看到自己的缺点和陷阱。请讲重点。这就是我问这个问题的原因。@alexeypro看到我的回答中的大量评论了吗?我正在使用的应用程序(在4台托管服务器中)在高峰时间占用了大约5G的会话数据,大大降低了速度。大多数数据都是缓存的,可以安全地丢弃——只要开发人员关心……@Vladimir:那么它很可能属于请求范围,或者可能属于应用程序范围。如果实际上在应用程序范围内,那么使用Java缓存框架,比如Ehcache或Terracotta。这些都是银行用户的数据。只是后端(HP NonStop)非常繁忙,最好将所有查询结果都保存在内存中,以防(通常情况下)再次需要相同的数据。EHCache对粘性会话(用户的所有请求都到达同一托管服务器)没有好处,并且需要复杂的设置(多播IP)。(事实上,在非粘性会话的情况下,EHCache会增加总内存消耗——因为每个节点上都有重复的数据)。会话有时是序列化的。SoftReference在这种情况下做什么?使用了另一个数据存储层。因此,如果我得到null,我就从存储中加载它。我的想法是保持它“包装”状态在SoftReference中,如果有太多用户登录,而有些用户没有使用应用程序的这一部分,但仍在活动会话中,则GC会进行清理。请查看Ehcache或Terracotta。
...
java.lang.ref.SoftReference softRef = session.getAttribute("mySoftRefData");
if (softRef != null && softRef.get() != null) {
   List<String> someData = (List<String>)softRef.get();
   // do something with it.
}
...