通常,Servlet只启动一次,Web容器简单为每个用户请求生成一个新线程。假设我是从头开始创建自己的Web容器而不是Threads,我只是将Servlets创建为Singleton。我在这里会遗漏什么吗?我想,在这种情况下,单例只能一次服务一个用户请求而不是多个。
答案 0 :(得分:4)
通常,Servlet只启动一次,Web容器简单为每个用户请求生成一个新线程。
第一个陈述是真的,但第二个陈述不是。通常,线程在应用程序启动期间创建一次并保存在线程池中。当线程完成其请求 - 响应处理作业时,它将返回到池中。这也是为什么在servletcontainer中使用ThreadLocal
必须小心谨慎的原因。
假设我是从头开始创建自己的Web容器而不是Threads,我只是将Servlets创建为Singleton。我会在这里遗漏什么吗?
他们不一定需要遵循单身模式。只需在应用程序启动期间创建它们的一个实例,并在整个应用程序的生命周期内将它们保存在内存中,然后让所有线程访问同一个实例。
我想,在这种情况下,单例只能一次服务一个用户请求,而不是多个。
事实并非如此。只有在应用程序范围的锁上同步对单例方法的访问时才会发生这种情况。例如,将synchronized
修饰符添加到servlet的方法中,或者将synchronized(this)
添加到管理器的方法中,并将请求委托给servlet。
答案 1 :(得分:1)
JavaEE曾经有过这样的机制 - 一个名为SingleThreadModel
的标记接口,您的servlet可以实现:
确保servlet一次只处理一个请求。这个界面没有方法。
如果servlet实现了此接口,则可以保证在servlet的服务方法中不会同时执行两个线程。 servlet容器可以通过同步对servlet的单个实例的访问,或者通过维护一个servlet实例池并将每个新请求分派给一个免费的servlet来实现这一保证。
请注意,SingleThreadModel不能解决所有线程安全问题。例如,即使使用SingleThreadModel servlet,仍可以同时在多个线程上通过多个请求访问会话属性和静态变量。建议开发人员采取其他方法来解决这些问题,而不是实现此接口,例如避免使用实例变量或同步访问这些资源的代码块。 Servlet API 2.4版中不推荐使用此接口。
容器可以使用它来为每个请求实例化一个新的servlet,或者如果他们选择的话,维护它们的池。
由于上述原因,这在Servlet 2.4中已弃用。同样的原因仍然适用于你的问题。
答案 2 :(得分:0)
基本上就是这样。
我会质疑创建自己容器的动机,其中有很多可用于各种用途。