Posted on 2007-01-25 20:29
兵临城下 阅读(1383)
评论(0) 编辑 收藏 所属分类:
Java EE
(以下所述只在WEB程序中)
近期在项目调试时遇到一个关于Servlet的实例变量的问题,由于Servlet是多线程的,所以Servlet的实例变量是非线程安全的,在项目调试中出现多线程的同步问题。
由于Web容器维护的Servlet在容器中只会创建一个实例,也就单例模式。Servlet多线程运行,则实例变量是多线程共享的,存在隐患,但很难发现!
下面来说一下这个问题,比较离奇:
原先的jsp页面中,存在一个Hidden的Iframe来实现页面上菜单联动的功能,一直运行良好。最近把iframe去掉了,改用ajax来实现。在下拉菜单onchange时,同时发出三个请求,调用同一个servlet,在这个Servlet中存在一个实例变量来返回数据,由于线程变量是非线程安全的,所以出现了bug,这个bug很隐秘,不是每次都能测试出来。
在这里我不想讨论iframe和ajax的好坏,只是想讨论一下实例变量和静态变量。
静态变量大家肯定比较熟悉,使用静态变量就是为了维护一个状态,使得可以让多实例共享这个变量,我们可以用它来实现一些类似缓存的功能。现在如果这个类的实现是一个单例的模式,那么静态变量就失去了优势。单例,那就意味着只能多线程使用,那么多线程中实例变量就是多线程共享的(非线程安全),此时实例变量的作用类似于静态变量了。
是不是可以这样说,单例模式中可以用实例变量来实现静态变量的功能呢?? 现在Spring中默认的都是单例模式(singleton)。
但是个人观点,不提倡使用实例变量,毕竟非线程安全。如果一定要使用的话,个人观点只用实例变量来维护一些web资源(缓存功能,如xml资源等等,公司项目中有很多这样的情况),不能在这个类中频繁使用它,不安全(我遇到的就是这样一个问题)。
纯属个人观点,欢迎大家发表意见,讨论一下!