Java 单例模式之饿汉模式 懒汉模式
2017-11-07 18:24
417 查看
单例模式有以下特点:
1. 单例类只能有一个实例。
2. 单例类必须自己创建自己的唯一实例。
3. 单例类必须给所有其他对象提供这一实例。
单例模式确保某个类只有一个实例。
单例模式实现有两种方式:
运行结果:
可以看到返回的是同一个实例。
饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。
运行结果:
也可写成下边这种形式,但每次都需要加锁,释放锁,效率低。
下面这种懒汉模式在多线程下,有可能创建出多个实例。所以不对。线程不安全
可以看到创建了多个实例。
这种方式当 LazySingle 类被装载了,instance 不一定被初始化。因为 SingleHolder 类没有被主动使用,只有显式通过调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance,实现懒加载。
1. 单例类只能有一个实例。
2. 单例类必须自己创建自己的唯一实例。
3. 单例类必须给所有其他对象提供这一实例。
单例模式确保某个类只有一个实例。
单例模式实现有两种方式:
1. 饿汉模式
public class HungrySingle { //这里方法均为static,其他类可直接使用。 private static final HungrySingle single = new HungrySingle(); private HungrySingle(){} //如果自己不创建构造方法,会自动创建无参public构造方法 public static HungrySingle getInstance(){ return single; } }
测试:
public class HungrySingle { //这里方法均为static,其他类可直接使用。 private static final HungrySingle single = new HungrySingle(); private HungrySingle(){} //如果自己不创建构造方法,会自动创建无参public构造方法 public static HungrySingle getInstance(){ return single; } public static void main(String[] args){ HungrySingle a = getInstance(); System.out.println(a); a = getInstance(); System.out.println(a); a = getInstance(); System.out.println(a); } }
运行结果:
可以看到返回的是同一个实例。
饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。
2. 懒汉模式
双重校验锁式public class LazySingle { private volatile static LazySingle single; private LazySingle(){} public static LazySingle getInstance(){ if(single == null){ synchronized (LazySingle.class) { //对类对象加锁,所有对象均不能同时运行。 if(single == null){ single = new LazySingle(); } } } return single; } }
测试
package Test; public class LazySingle { private volatile static LazySingle single; private LazySingle(){} public static LazySingle getInstance(){ if(single == null){ synchronized (LazySingle.class) { if(single == null){ single = new LazySingle(); } } } return single; } public static void main(String[] args) { LazySingle single = getInstance(); System.out.println(single); single = getInstance(); System.out.println(single); single = getInstance(); System.out.println(single); } }
运行结果:
也可写成下边这种形式,但每次都需要加锁,释放锁,效率低。
public class LazySingle { private static LazySingle single; private LazySingle(){} public static LazySingle getInstance(){ synchronized (LazySingle.class) { if(single == null){ single = new LazySingle(); } return single; } } }
下面这种懒汉模式在多线程下,有可能创建出多个实例。所以不对。线程不安全
public class LazySingle { private static LazySingle single; private LazySingle(){} public static LazySingle getInstance(){ if(single == null){ single = new LazySingle(); } return single; } }
测试:
package Test; class multiSingle implements Runnable{ @Override public void run() { LazySingle single = LazySingle.getInstance(); System.out.println(single); } } public class LazySingle { private static LazySingle single; private LazySingle(){} public static LazySingle getInstance(){ if(single == null){ for(int i = 0; i < 100000; ++i){ i++; i--; } single = new LazySingle(); } return single; } public static void main(String[] args) { for(int i = 0; i < 100; ++i){ new Thread(new multiSingle()).start(); } } }
运行结果:
可以看到创建了多个实例。
3.懒汉模式-静态内部类写法
这种方式能达到双检锁方式一样的功效,但实现更简单。这种方式利用了 ClassLoader 机制来保证初始化 instance 时只有一个线程,从而保证线程安全。这种方式当 LazySingle 类被装载了,instance 不一定被初始化。因为 SingleHolder 类没有被主动使用,只有显式通过调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance,实现懒加载。
public class LazySingle { private static class SingleHolder{ private static final LazySingle instance = new LazySingle(); } private LazySingle() {} public static LazySingle getInstance() { return SingleHolder.instance; } }
相关文章推荐
- java 单例模式(饿汉模式与懒汉模式)
- java 单例模式 -饿汉 -懒汉
- JAVA单例设计模式(饿汉懒汉)
- Java基础 - 单例(饿汉、懒汉),Runtime类,Timer,线程通信,互斥锁,线程组,线程五种状态,线程池,工厂模式,GUI,适配器设计模式
- java中的懒汉单例模式和饿汉单例模式
- java的设计模式之单利设计模式(饿汉和懒汉)
- Java设计模式之单例模式(懒汉/饿汉)
- 从java.lang.Runtime看单例懒汉饿汉模式的选择
- java 单例模式之线程安全的饿汉模式和懒汉模式
- Java中的单例设计模式之饿汉模式、懒汉模式
- 从java.lang.Runtime看单例懒汉饿汉模式的选择
- Java设计模式中单例模式(Design Pattern):懒汉模式和饿汉模式
- java单例饿汉和懒汉模式
- Java 单例模式(饿汉+懒汉)
- JAVA基础单例的特殊模式饿汉与懒汉模式
- java设计模式之单例模式写法,懒汉,饿汉,双检锁
- 单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举
- 单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举。
- 单例模式--饿汉和懒汉异同
- 单例模式——(饿汉模式和懒汉模式)