Java 如何使jsp spring应用程序线程安全?
我有一个jsp应用程序(使用Spring),它使用了几个全局变量。然而,我需要多人同时使用这个程序。使程序的每个实例都独立于其他实例的线程安全的最佳方法是什么Java 如何使jsp spring应用程序线程安全?,java,spring,jsp,concurrency,thread-safety,Java,Spring,Jsp,Concurrency,Thread Safety,我有一个jsp应用程序(使用Spring),它使用了几个全局变量。然而,我需要多人同时使用这个程序。使程序的每个实例都独立于其他实例的线程安全的最佳方法是什么 ::编辑::如果不使用任何单例对象,我可以吗?每个请求都在自己的线程中处理。这些线程由servlet容器管理。在servlet中使用静态全局变量不是一个好主意。所有实例变量对于所有线程都是公共的,因此它可能导致不明确的状态 我建议将此类型信息保存在范围变量(应用程序、会话、请求、页面等)中 如果必须使用全局变量,则需要同步对该变量的访问以
::编辑::如果不使用任何单例对象,我可以吗?每个请求都在自己的线程中处理。这些线程由servlet容器管理。在servlet中使用静态全局变量不是一个好主意。所有实例变量对于所有线程都是公共的,因此它可能导致不明确的状态 我建议将此类型信息保存在范围变量(应用程序、会话、请求、页面等)中
如果必须使用全局变量,则需要同步对该变量的访问以避免未知状态。每个请求都在其自己的线程中处理。这些线程由servlet容器管理。在servlet中使用静态全局变量不是一个好主意。所有实例变量对于所有线程都是公共的,因此它可能导致不明确的状态 我建议将此类型信息保存在范围变量(应用程序、会话、请求、页面等)中
如果必须使用全局变量,则需要同步对该变量的访问以避免未知状态。典型的容器使用每个请求一个线程的模型,因此您有一个易于识别的内置边界。一般规则是永远不要在对多个请求(线程)可见的任何对象中存储任何状态,除非该状态实际上是不可变的。例如,像这样的单例控制器
@Controller
@RequestMapping("/schedule")
class MyController {
private Scheduler scheduler;
@RequestMapping(method = RequestMethod.POST)
public void scheduleSomething(Foo foo) {
scheduler.schedule(foo);
}
}
是有状态的——schedular字段保存状态——但状态在启动时初始化,并且在所有请求/线程中保持不变。另一方面,如果您有这样的单例控制器:
@Controller
@RequestMapping("/schedule")
class MyController {
private Scheduler scheduler;
private Foo foo;
@RequestMapping(method = RequestMethod.POST)
public void scheduleSomething(Foo foo) {
this.foo = foo;
scheduler.schedule(this.foo);
}
}
对于并发访问来说,这是绝对不安全的,因为所有请求都会转到同一个控制器,并且foo将以非线程安全的方式不断变化。在整个应用程序中遵循这条推理路线,您将是安全的。一个典型的容器使用每请求一个线程的模型,因此您有一个易于识别的内置边界。一般规则是永远不要在对多个请求(线程)可见的任何对象中存储任何状态,除非该状态实际上是不可变的。例如,像这样的单例控制器
@Controller
@RequestMapping("/schedule")
class MyController {
private Scheduler scheduler;
@RequestMapping(method = RequestMethod.POST)
public void scheduleSomething(Foo foo) {
scheduler.schedule(foo);
}
}
是有状态的——schedular字段保存状态——但状态在启动时初始化,并且在所有请求/线程中保持不变。另一方面,如果您有这样的单例控制器:
@Controller
@RequestMapping("/schedule")
class MyController {
private Scheduler scheduler;
private Foo foo;
@RequestMapping(method = RequestMethod.POST)
public void scheduleSomething(Foo foo) {
this.foo = foo;
scheduler.schedule(this.foo);
}
}
对于并发访问来说,这是绝对不安全的,因为所有请求都会转到同一个控制器,并且foo将以非线程安全的方式不断变化。在整个应用程序中遵循这条推理路线,您将是安全的。所以基本上没有单例对象?@Steve-您的问题是关于全局(和/或静态)变量的。我希望你没有把它们混在一起。要回答您的评论,您可以使用singleton,只要它们保存在
ServletContext
中即可。啊,我认为它们基本上是一样的。谢谢。@Steve-不,它们不一样。最重要的是,singleton是一种设计模式。谷歌“singleton模式java”来更好地理解它。详细回答这个问题超出了我的范围。如果这些单例请求是独立的和不变的,那么单例就可以了。他的建议是把信息放在适当的范围内。特定于用户但不是请求的数据放入会话范围。特定于请求的数据,放入请求范围等。在单例对象中,任何全局的、不能更改的数据都可以。这就是它们的用途。所以基本上没有单例对象?@Steve-你的问题是关于全局(和/或静态)变量的。我希望你没有把它们混在一起。要回答您的评论,您可以使用singleton,只要它们保存在ServletContext
中即可。啊,我认为它们基本上是一样的。谢谢。@Steve-不,它们不一样。最重要的是,singleton是一种设计模式。谷歌“singleton模式java”来更好地理解它。详细回答这个问题超出了我的范围。如果这些单例请求是独立的和不变的,那么单例就可以了。他的建议是把信息放在适当的范围内。特定于用户但不是请求的数据放入会话范围。特定于请求的数据,放入请求范围等。在单例对象中,任何全局的、不能更改的数据都可以。这就是它们的目的。如果它们没有可变状态,那么单例就完全可以了。默认情况下,SpringBean是单例的,但是传统多层应用程序中的大多数SpringBean都没有状态。如果没有可变状态,单例就完全可以了。默认情况下,Springbean是单例的,但传统多层应用程序中的大多数Springbean都没有状态。