我知道对于servlet的每个请求都会执行doPost()或doGet()方法,而init()方法中的代码只会初始化一次。但是在所有这些方法之外编写的代码呢?
那个代码还有线程吗?我的意思是在该部分中声明的变量,如果它们在doPost()
中被修改,那么这些变化是否会反映给servlet的其他请求?
答案 0 :(得分:5)
在普通的servlet容器中,只有一个servlet对象的实例。任何数量的线程都可以使用此对象 - 每个请求一个线程。管理servlet实例的生命周期取决于servlet容器。
因此,在任何方法(包括init())中更改类变量的值时,它将影响所有后续请求。 在您的方法中更改或声明局部变量当然不会影响任何事情,因为下次调用该方法时,会再次创建局部变量(并在方法完成时被垃圾收集器销毁)。
答案 1 :(得分:3)
通过defaut Servlet不是线程安全的。将为许多客户端调用单个servlet实例。将状态存储在servlet中作为实例变量是完全错误的。
<强>参考文献:强>
答案 2 :(得分:1)
Servlet实例由容器合并。因此,任何数量的Servlet对象都可以由真实场景中的任意数量的线程共享。所有doXXX()方法和从它们调用的其他方法都将由Threads共享。
因此,在Servlet中拥有类级别变量(维护状态)是非常不鼓励的。虽然你肯定可以使用常量共享的常量,静态辅助方法和静态变量,但不会被使用Servlet的客户端不断修改。
虽然不鼓励使用,但是没有阻止你使变量/方法同步。这将确保一次只有一个线程访问资源,但是会有性能损失,因为线程可能必须等待其他人在占用锁之前先释放资源。
但是有一种更好的方法,如果你希望用Servlet维护状态并希望每个客户端存储变量,你的Servlet应该实现javax.servlet.SingleThreadModel
。如果你的Servlet实现了这个标记接口,容器就会知道它维护状态,因此每个实例只能提供一个线程。