struts action singleton

时间:2011-04-13 13:38:07

标签: multithreading struts

为什么struts动作类是单例?

实际上我明白它是多线程的。但是当有数千个请求执行相同的操作时,我们将同步用于防止线程问题,那么它不能提供良好的性能bcoz线程进入等待状态并且需要时间来进行处理。

这是否可以从动作类中删除单例?

了解更多信息请访问:http://rameshsengani.in

3 个答案:

答案 0 :(得分:21)

你问为什么Action类是单例,但我认为你也有一些理解线程安全性的问题所以我会尝试解释它们。

首先,Struts Action类没有实现为单例,框架只使用它的一个实例。但是因为只有一个实例用于处理所有传入的请求,所以必须注意不要在非线程安全的Action类中执行某些操作。但问题是:默认情况下,Struts Action类不是线程安全的

Thread safety表示可以在多线程环境中安全地使用一段代码或对象。 Action类可以安全地用在多线程环境中,你可以同时在一千个线程中使用它而没有任何问题......如果你正确实现它

来自Action class JavaDoc

  

必须以线程安全的方式对操作进行编程,因为控制器将为多个同时请求共享同一实例。这意味着您应该考虑以下项目进行设计:

     
      
  • 实例和静态变量不得用于存储与特定请求状态相关的信息。它们可用于跨同一行动的请求共享全局资源。

  •   
  • 如果这些资源需要保护,则必须同步对其他资源(JavaBeans,会话变量等)的访问。 (但一般情况下,资源类应设计为在必要时提供自己的保护。

  •   

您可以通过派生并创建自己的Struts Action来使用它。当您这样做时,您必须注意遵守上述规则。这意味着像这样的NO-NO:

public class MyAction extends Action {
   private Object someInstanceField;
   public ActionForward execute(...) {
      // modify someInstanceField here without proper synchronization ->> BAD
   }
}

除非你在上面的代码中做错了,否则你不需要同步Action类。问题在于执行操作的切入点是execute方法。

此方法接收所有需要的参数。您可以在execute方法中同时执行一千个线程而不会出现问题,因为每个线程都有自己的执行堆栈用于方法调用,但不适用于堆中的数据(如someInstanceField),在所有线程之间共享。

在修改someInstanceField时没有正确的同步,所有线程都可以随意使用它。

所以,是的,Struts 1 Action类不是线程安全的,但这是因为你不能安全地将状态存储在它们中(即使它们成为statefulf),或者如果你这样做必须正确同步。

但是如果你保持你的Action类实现无状态,你就可以了,不需要同步,线程也不会等待。

  

为什么struts动作类是单例?

这是设计的。 JavaDoc再次解释了它:

  

Action是传入HTTP请求的内容与应该执行以处理此请求的相应业务逻辑之间的适配器

请求参数绑定到Web层,您不希望将该类型的数据发送到业务逻辑类中,因为这会产生紧密耦合 在这两个层之间,这将使您无法轻松重用业务层。

因为将Web对象转换为模型对象(我并不是说ActionForm bean在这里)应该是Action类的主要目的,所以它们不需要维护任何状态(并且不应该),并且没有理由拥有这些家伙的更多实例,所有人都做同样的事情。只有一个人会这样做。

如果您希望通过将信息保存到数据库中,可以安全地维护模型中的状态,或者您可以使用http会话维护Web状态。在Action类中维护状态是错误的,因为这引入了同步化的需要,如上所述。

  

有没有办法从动作类中删除单例?

我猜你可以扩展Struts并覆盖RequestProcessor.processActionCreate的默认行为,为每个请求创建一个Action 但这意味着在Struts之上添加另一个层来改变其“正常”行为。我已经看到这样的东西在一些应用程序中变坏了所以我不推荐它。

我的建议是让你的Action类保持无状态,并选择为它创建的单个实例。

如果您的应用是新的,并且您绝对需要有状态的操作,我想您可以选择Struts 2(他们在那里更改了设计,现在每个请求都有一个Action实例)。 But Struts 2 is very different from Struts 1因此,如果你的应用程序已经过时,可能很难迁移到Struts 2。

希望现在能说清楚。

答案 1 :(得分:2)

这已在Struts2 http://struts.apache.org/release/2.1.x/docs/comparing-struts-1-and-2.html

中发生了变化

* Struts 2 Action对象针对每个请求进行实例化,因此没有线程安全问题。 (实际上,servlet容器会为每个请求生成许多丢弃对象,而另外一个对象不会对性能造成影响或影响垃圾回收。)*

答案 2 :(得分:1)

我对struts知之甚少,但看起来this changed in Struts 2,所以也许你应该切换到Struts 2