servlet 单例问题

servlet是单例的,即在web服务器中最多只存在servlet的一个实例,那么servlet就是线程不安全的。下面通过以下代码模拟买票过程:

package com.zjb.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyServlet1 extends HttpServlet {
    private int ticket = 2;

    /**
     * The doGet method of the servlet. <br>
     *
     * This method is called when a form has its tag value method equals to get.
     *
     * @param request
     *            the request send by the client to the server
     * @param response
     *            the response send by the server to the client
     * @throws ServletException
     *             if an error occurred
     * @throws IOException
     *             if an error occurred
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        // out.println("hello,I am the first Myeclipse servlet,the currentTime is "
        // + new Date().toString());
        if(ticket>0){
            System.out.println("恭喜你,买到票了");
            try {
                Thread.sleep(10*1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            ticket--;
        }else{
            System.out.println("對不起,已經沒有票了");
        }
        out.close();
    }

    /**
     * The doPost method of the servlet. <br>
     *
     * This method is called when a form has its tag value method equals to
     * post.
     *
     * @param request
     *            the request send by the client to the server
     * @param response
     *            the response send by the server to the client
     * @throws ServletException
     *             if an error occurred
     * @throws IOException
     *             if an error occurred
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doGet(request, response);
    }

}

从上面代码可以看出,现在一共有2张票,即只有2个请求可以买到票,然而当从浏览器发出三次请求是却出现了下面的结果:

那么,这种由单例造成的线程不安全问题该如何解决呢?只要把操作共享资源(如ticket)的代码加同步锁即可:

synchronized (this) {
            if(ticket>0){
                System.out.println("恭喜你,买到票了");
                try {
                    Thread.sleep(10*1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                ticket--;
            }else{
                System.out.println("對不起,已經沒有票了");
            }
        }
时间: 2024-10-30 01:50:52

servlet 单例问题的相关文章

Servlet 单例多线程【转】

源地址:Servlet 单例多线程 Servlet如何处理多个请求访问?Servlet容器默认是采用单实例多线程的方式处理多个请求的:1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例):2.容器初始化化Servlet主要就是读取配置文件(例如tomcat,可以通过servlet.xml的<Connector>设置线程池中线程数目,初始化线程池通过web.xml,初始化每个参数值等等.3.当请求到达时,Servlet容器通过

Java学习资料-Servlet单例多线程

Servlet 单例多线程 Servlet如何处理多个请求访问? Servlet容器默认是采用单实例多线程的方式处理多个请求的: 1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例): 2.容器初始化化Servlet主要就是读取配置文件(例如tomcat,可以通过servlet.xml的<Connector>设置线程池中线程数目,初始化线程池通过web.xml,初始化每个参数值等等. 3.当请求到达时,Servlet容器通过

[转]Servlet 单例多线程

Servlet如何处理多个请求访问? Servlet容器默认是采用单实例多线程的方式处理多个请求的: 1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例): 2.容器初始化化Servlet主要就是读取配置文件(例如tomcat,可以通过servlet.xml的<Connector>设置线程池中线程数目,初始化线程池通过web.xml,初始化每个参数值等等. 3.当请求到达时,Servlet容器通过调度线程(Dispatcha

Servlet单例多线程

Servlet如何处理多个请求访问?Servlet容器默认是采用单实例多线程的方式处理多个请求的:1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例):2.容器初始化化Servlet主要就是读取配置文件(例如tomcat,可以通过servlet.xml的<Connector>设置线程池中线程数目,初始化线程池通过web.xml,初始化每个参数值等等.3.当请求到达时,Servlet容器通过调度线程(Dispatchaer T

Servlet 单例多线程

转自:http://www.cnblogs.com/yjhrem/articles/3160864.html Servlet如何处理多个请求访问? Servlet容器默认是采用单实例多线程的方式处理多个请求的: 1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例): 2.容器初始化化Servlet主要就是读取配置文件(例如tomcat,可以通过servlet.xml的 设置线程池中线程数目,初始化线程池通过web.xml,初始

struts2的action是多例,servlet是单例

struts2中action是多例的,即一个session产生一个action如果是单例的话,若出现两个用户都修改一个对象的属性值,则会因为用户修改时间不同,两个用户访问得到的 属性不一样,操作得出的结果不一样.举个例子:有一块布长度300cm,能做一件上衣(用掉100cm)和一件裤子(用掉200cm);甲和乙同时访问得到的 长度都是300cm,甲想做上衣和裤子,他先截取100cm去做上衣,等上衣做完再去做裤子,而乙这时正好也拿100cm去做上衣,那 好,等甲做完上衣再做裤子的时候发现剩下的布(

单例 (JAVA)

java中单例模式是一种常见的设计模式,以下是它的特点: 单例类只能有一个实例. 单例类必须自己创建自己的唯一实例. 单例类必须给所有其他对象提供这一实例 第一种(懒汉,线程不安全): 1 public class Singleton {   2     private static Singleton instance;   3 private Singleton (){}    4     public static Singleton getInstance() {   5     if 

GOF设计模式之1:单例设计模式

1.单例设计模式核心作用: 保证一个类只有一个实例,并且提供了访问该实例的全局访问点 2.常见应用场景: window的任务管理器 项目中读取配置文件一般也是一个单例模式 数据库连接池的设计也是采用单例模式,因为数据库连接是一种数据库资源 操作系统的文件管理系统,也是单例模式,一个操作系统只能有一个文件系统 Application也是单例的应用(Servlet编程或者Android的Application类) 在Spring中,每个bean默认也是单例的,这样的有点儿事Spring容器可以管理

单例设计模式-java

第一种(懒汉,线程不安全): 1 public class Singleton { 2 private static Singleton instance; 3 private Singleton (){} 4 5 public static Singleton getInstance() { 6 if (instance == null) { 7 instance = new Singleton(); 8 } 9 return instance; 10 } 11 } 这种写法lazy load