什么是Servlet及原理 这个执行绪安全问题我都没见过
什么是Servlet

Servlet(Server Applet),全称Java Servlet,未有中文译文。是用Java编写的服务器端程式。其主要功能在于互动式地浏览和修改资料,生成动态Web内容。狭义的Servlet是指Java语言实现的一个界面,广义的Servlet是指任何实现了这个Servlet界面的类,一般情况下,人们将Servlet理解为后者。
Servlet运行于支援Java的应用服务器中。从实现上讲,Servlet可以响应任何型别的请求,但绝大多数情况下Servlet只用来扩充套件基于HTTP协议的Web服务器。
Servlet 的工作原理
Servlet界面定义了Servlet与servlet容器之间的契约。这个契约是:Servlet容器将Servlet类载入内存,并产生Servlet例项和呼叫它具体的方法。但是要注意的是,在一个应用程序中,每种Servlet型别只能有一个例项。
使用者请求致使Servlet容器呼叫Servlet的Service()方法,并传入一个ServletRequest物件和一个ServletResponse物件。ServletRequest物件和ServletResponse物件都是由Servlet容器(例如TomCat)封装好的,并不需要程序员去实现,程序员可以直接使用这两个物件。
ServletRequest中封装了当前的Http请求,因此,开发人员不必解析和操作原始的Http资料。ServletResponse表示当前使用者的Http响应,程序员只需直接操作ServletResponse物件就能把响应轻松的发回给使用者。
对于每一个应用程序,Servlet容器还会建立一个ServletContext物件。这个物件中封装了上下文(应用程序)的环境详情。每个应用程序只有一个ServletContext。每个Servlet物件也都有一个封装Servlet配置的ServletConfig物件。
Servlet 生命周期
Servlet 生命周期可被定义为从建立直到毁灭的整个过程。以下是 Servlet 遵循的过程:
Servlet 通过呼叫 init () 方法进行初始化。
Servlet 呼叫 service() 方法来处理客户端的请求。
Servlet 通过呼叫 destroy() 方法终止(结束)。
最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
现在让我们详细讨论生命周期的方法。
init() 方法
init 方法被设计成只调用一次。它在第一次建立 Servlet 时被呼叫,在后续每次使用者请求时不再呼叫。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。
Servlet 创建于使用者第一次呼叫对应于该 Servlet 的 URL 时,但是您也可以指定 Servlet 在服务器第一次启动时被载入。
当用户呼叫一个 Servlet 时,就会建立一个 Servlet 例项,每一个使用者请求都会产生一个新的执行绪,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地建立或载入一些资料,这些资料将被用于 Servlet 的整个生命周期。
service() 方法
service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)呼叫 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。
每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的执行绪并呼叫服务。service() 方法检查 HTTP 请求型别(GET、POST、PUT、DELETE 等),并在适当的时候呼叫 doGet、doPost、doPut,doDelete 等方法。
doGet() 方法
GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。
doPost() 方法
POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。
destroy() 方法
destroy() 方法只会被呼叫一次,在 Servlet 生命周期结束时被呼叫。destroy() 方法可以让您的 Servlet 关闭数据库连线、停止后台执行绪、把 Cookie 列表或点选计数器写入到磁盘,并执行其他类似的清理活动。
执行绪安全问题
1.Servlet执行绪安全问题产生的原因
Servlet以单例的形式执行在多执行绪的环境中,其中的例项变数储存在堆中的物件中,而堆是多执行绪共享的,因此例项变数存线上程安全问题,而静态变数储存在方法区,方法区也是多执行绪共享的,静态变数也存线上程安全问题,而区域性变脸储存在栈中,栈中的资料在内部是共享的,在栈间是不共享的,即一个执行绪一个栈,因此区域性变数时执行绪安全的。
2.执行绪安全问题的解决方案:
将全域性变数转化为区域性变数。
将修改全域性变数的程式码新增到同步方法或者同步块中。
将全域性变数储存到ThrealLocal中,为每一个执行绪分配一个变数的副本,各个执行绪相互独立操作。