单例模式:保证仅有一个实例,并可提供访问该实例的全局访问点
实现:(1)将类的构造器私有,保证了只能通过静态方法获取该类实例
(2)静态类属性保证了每次返回的实例都是同一个
(3)静态方法返回该属性。
懒汉式:
package offer.sheji;
/*
懒汉式:
用到再创建
优点:实现简单,可能节约内存
缺点:synchronized方法效率低,如果去掉的话,存在线程安全问题
*/
public class SingletonLazy {
private static SingletonLazy uniqueInstance;
private int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
private SingletonLazy() {
System.out.println("构造函数执行");
}
public static synchronized SingletonLazy getUniqueInstance() {
if(uniqueInstance==null){
uniqueInstance=new SingletonLazy();
}
return uniqueInstance;
}
public static void main(String[] args) {
SingletonLazy s1=SingletonLazy.getUniqueInstance();
SingletonLazy s2=SingletonLazy.getUniqueInstance();
System.out.println(s1==s2);
s1.setValue(1);
s2.setValue(2);
System.out.println(s1.getValue());
System.out.println(s2.getValue());
}
}
结果:
构造函数执行
true
2
2
package offer.sheji;
public class SingletonHungry {
/*
饿汉模式,立即加载
优点,没有多线程问题
缺点:类一经加载,实例对象会一直存在,浪费内存
*/
private static SingletonHungry uniqueInstance=new SingletonHungry();
private SingletonHungry() {
System.out.println("构造函数");
}
public static SingletonHungry getUniqueInstance() {
System.out.println("正在获取");
return uniqueInstance;
}
public static void main(String[] args) {
SingletonHungry sh=SingletonHungry.getUniqueInstance();
}
}
双检查锁机制DCL(double checked locking):
package offer.sheji;
public class SingletonDemo {
/*
双检查锁机制:DCL
优点:效率高,线程安全且满足多线程操作原子性
*/
private volatile static SingletonDemo instance;
private SingletonDemo(){
System.out.println("正在构造");
}
public static SingletonDemo getInstance() {
if(instance==null){
synchronized (SingletonDemo.class){
//某个线程获得了类锁,类锁,获得当前类的class实例
// 即同步了一次,并且只有唯一线程进入这里
//再判断一次instance是否创建。
if(instance==null)
instance=new SingletonDemo();
}
}
return instance;
}
public static void main(String[] args) {
SingletonDemo.getInstance();
}
}
/**
volatile :禁止JVM使用 指令重排
没有最好只有最合适---- 如果频繁调用的话,饿汉,如果几乎不调用并且是单线程情况,用不带线程的懒汉,如果综合一点,就用双检查锁机制。