1、单例模式使用原因:
有些时候,允许自由创建某个类的实例没有意义,还可能造成系统性能下降(因为创建对象所带来的系统开销问题)。Hibernate访问时只需要一个SessionFactory实例。如果一个类始终只能创建一个实例,则这个类被称为单例类,这种模式称为单例模式。
Spring推荐将所有业务逻辑组件、DAO组件、数据源组件等配置成单例的行为方式,因为这些组件无须保存任何用户状态,故所有客户端都可以共享这些业务逻辑组件、DAO组件。
package command;
/**
* @todo
* @author 成明俊
* @email 1047914020@qq.com
* @date 2020年3月20日
*/
class Singleton{
//使用一个变量来缓存曾经创建的实例
private static Singleton instance;
//将构造器使用private修饰,隐藏该构造器
private Singleton() {}
//提供一个静态方法,用于返回Singleton实例
//该方法可以加入自定义的控制,保证只产生一个Singleton对象
public static Singleton getInstance() {
//如果instance为null,表面还不曾创建Singleton对象
//如果instacne不为null,则表明已经创建了Singleton对象,将不会执行该方法
if(instance == null) {
//创建一个Singleton对象,将其缓存起来
instance = new Singleton();
}
return instance;
}
}
public class SingletonTest{
public static void main(String[] args) {
//创建Singleton对象不能通过构造器,只能通过getInstance方法
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2);
}
}
单例模式的优势:
减少创建Java实例带来的的系统开销
便于系统跟踪单个Java实例的生命周期、实例状态等。
2、单例模式的两种形态
2.1懒汉模式:
public class LazySingleton
{
private static volatile LazySingleton instance=null; //保证 instance 在所有线程中同步
private LazySingleton(){} //private 避免类在外部被实例化
public static synchronized LazySingleton getInstance()
{
//getInstance 方法前加同步
if(instance==null)
{
instance=new LazySingleton();
}
return instance;
}
}
注意:如果编写的是多线程程序,则不要删除上例代码中的关键字 volatile 和 synchronized,否则将存在线程非安全的问题。如果不删除这两个关键字就能保证线程安全,但是每次访问时都要同步,会影响性能,且消耗更多的资源,这是懒汉式单例的缺点。
2.2饿汉模式:
public class HungrySingleton
{
private static final HungrySingleton instance=new HungrySingleton();
private HungrySingleton(){}
public static HungrySingleton getInstance()
{
return instance;
}
}
饿汉式单例在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现问题。