单例模式:一个类仅能有一个实例,并且向整个系统提供这一个实例。
单例模式的特点:
(1)单例类仅能有一个实例。
(2)单例类必须为自己创建实例。
(3)单例类必须向外界提供获取实例的方法。
单例模式的形式:(1)懒汉式 、(2)恶汉式、(3)枚举式
一、懒汉式(能够延迟加载)
class Singleton {
private static Singleton instance = null;
int value = 10;
//私有的构造函数
private Singleton() {}
//获取单例实例对象
public static Singleton getInstance() {
if(instance == null) {
//延迟加载,在真正需要的时候才创建单例对象
instance = new Singleton();
}
return instance;
}
public int getValue() {
return value;
}
}
但是以上的代码是线程不安全的,多线程并发的情况下,SingleTon可能产生多个实例。
改进方法
1、在getInstance()方法上加同步锁
//(1)使用同步锁synchronized保证线程安全
class Singleton {
private static Singleton instance = null;
private int value = 10;
private Singleton() {}
public static synchronized Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
public int getValue() {
return value;
}
}
class Singleton {
private int value = 10;
// 静态内部类
private static class SingletonClassInstance {
private static final Singleton instance = new Singleton();
}
private Singleton() {
}
public static Singleton getInstance() {
return SingletonClassInstance.instance;
}
public int getValue() {
return value;
}
}
3、双重校验锁 (不推荐)
/**
*
* @author tao
*
* 懒汉模式(双重校验锁[不推荐])单例
*/
public class Singleton {
private volatile static Singleton instance = null;
private int value = 10;
private Singleton() {
}
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
public int getValue() {
return value;
}
}
二、恶汉式(不能延迟加载)
class Singleton {
//类初始化时,立即加载这个对象,加载类时,天然的是线程安全的!
private static Singleton instance = new Singleton();
private int value = 10;
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
public int getValue() {
return value;
}
}
饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。
使用方法:
public class SingletonTest {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
System.out.println(singleton.getValue());
}
三、枚举式(线程安全的)
JVM会保证enum不能被反射并且构造器方法只执行一次
enum Singleton {
//此枚举类的唯一实例
INSTANCE;
//其他成员和其他方法
private int value = 10;
public int getValue() {
return value;
}
}
public class SingletonTest {
public static void main(String[] args) {
Singleton singleton = Singleton.INSTANCE;
System.out.println(singleton.getValue());
}
}