最近做项目遇到了一个问题,看了很久都没有得到解决,问题描述如下:
用Java实现了文件上传的后台代码,主要文件是UploadServlet,那么在上传的时候会发现当我上传一个文件的时候会触发多个连接数据库的操作,这样上传多个文件就会触发更多的操作,这样就会是一个遭难,因为数据库连接数过多就会造成以后创建失败。仔细观察一下有问题的伪代码:
public class UploadServlet extends HttpServlet{ private FileService fileservice ; public void upload() { fileservice = new FileService(); //fileService负责对文件的增删查改工作 fileservice.create(file); //file是上传文件对象,调用create方法创建数据库连接,写入数据库 } }
public class FileService{ private static FileService fileservice; private FileService(){ /*do something*/ } public static FileService getInstance(){ if(fileservice==null){ //如果fileservice没有被初始化,那么就new出新的空间 fileservice = new FileService(); //这句代码只会被执行一次 } return fileservice; //返回对象唯一的变量fileservice } /*do something....*/ } public class UploadServlet extends HttpServlet{ private static FileService fileservice ; public void upload() { fileservice = FileService.getInstance(); //fileService负责对文件的增删查改工作 fileservice.create(file); //file是上传文件对象,调用create方法创建数据库连接,写入数据库 } }
public class Singleton { private static Singleton uniqueInstance;//利用一个静态变量来记录Singleton类的唯一实例 /*把构造函数声明为私有的,只有自己Singleton类内才可以调用构造函数*/ private Singleton(){ /* do something... */ } public static Singleton getInstance(){ if(uniqueInstance==null){ //如果uniqueInstance是空的,说明还没有创建实例 /*如果它不存在,我们就利用私有的构造器产生一个Singleton实例并把它赋值到 * uniqueInstance静态变量中。请注意,如果我们不需要这个实例,它就永远 * 不会产生。这就是所谓的“延迟实例化”*/ uniqueInstance = new Singleton(); } /*如果uniqueInstance不是null,就表示之前已经创建过对象。我么就直接跳到return语句*/ return uniqueInstance;//当执行到这个return,就表示我们已经有了实例,并将uniqueInstance当返回值 } }>单例常常被用来管理共享的资源,例如数据库连接或者线程池。
//Singleton.h #ifndef _SINGLETON_H_ #define _SINGLETON_H_ #include<iostream> using namespace std; class Singleton { public: static Singleton * GetInstance(); private: Singleton(); static Singleton* unique_instance; }; #endif
//Singleton.cc #include "Singleton.h" #include<iostream> using namespace std; Singleton* Singleton:: unique_instance = NULL; Singleton::Singleton() { cout<<"singleton constructor"<<endl; } Singleton* Singleton:: GetInstance() { if( unique_instance == NULL ) { unique_instance = new Singleton(); } return unique_instance; }
//main.cc #include<iostream> #include "Singleton.h" using namespace std; int main() { Singleton* sgn1 = Singleton::GetInstance(); Singleton* sgn2 = Singleton::GetInstance(); system("pause") ; return 0; }
public class Singleton{ private static Singleton uniqueInstance; private Singleton(){} /*通过增加synchronized关键字到getInstance()方法中,我们迫使每个线程在进入这个方法之前,要先等候别的线程离开该方法。也就是说,不会有两个线程可以同时进入这个方法*/ public static synchronized Singlgeton getInstance{ if(uniqueInstance == null){ uniqueInstance = new Singleton(); } return uniqueInstance; } //其他有用的方法 }
public class Singleton{ private static Singleton uniqueInstance = new Singleton();//在静态初始化器(static initialize)中创建单件。这段代码保证了线程安全(thread safe) private Singleton(){} public static Singlgeton getInstance{ return uniqueInstance; //已经有实例了,直接使用它。 } }利用这个做法,我们依赖JVM在加载这个类时马上创建此唯一的单件实例。JVM保证在任何线程访问uniqueInstance静态变量之前,一定先创建此实例。
public class Singleton{ private volatile static Singleton uniqueInstance;//volatile关键字确保:当uniqueInstance变量被初始化成Singleton实例时,多个线程正确地处理uniqueInstance变量。 private Singleton(); public static Singleton getInstance(){ if(uniqueInstance == null){ //检查实例,如果不存在,就进入同步区块。 sychronized(Singleton.class){ if(uniqueInstance==null){ //进入区块后,再检查一次。如果仍是null,才创建实例。 uniqueInstance = new Singleton(); } } } return uniqueInstance; } }如果性能是你关心的重点,那么这个做法可以帮你打打地减少getInstance()的时间耗费。