单例模式有三种:
饿汉模式:提前初始化好对象,需要的时候直接调用
package com.whereta.singleton; /** * Vincent 创建于 2016/4/15. * 该模式是提前初始化好对象,调用的时候直接返回即可 */ public class SingletonClass1 { //一定要将默认的构造函数设为私有,不能实例化 private SingletonClass1() { } private static SingletonClass1 instance = new SingletonClass1(); public static SingletonClass1 getInstance() { return instance; } public void test(){ System.out.println("我是:"+this); } }
懒汉模式-双重检查加锁:在调用的时候检查对象是否实例化,如果没有实例化则实例化返回
package com.whereta.singleton; /** * Vincent 创建于 2016/4/15. * 该模式是懒汉模式,在具体使用的时候初始化。采用双重检查加锁方式保证线程安全, */ public class SingletonClass2 { //一定要将默认的构造函数设为私有,不能实例化 private SingletonClass2() { } private static SingletonClass2 instance = null; public static SingletonClass2 getInstance() { if (instance == null) { //如果为空,加锁开始初始化 synchronized (SingletonClass2.class) { SingletonClass2 temp = instance; if (temp == null) { //此处保存对象创建成功之后再返回,如果不添加temp,则会出现问题: // 当instance先分配内存空间,未完成数据设置,此时instance不为null,如果有新的线程进入请求,直接返回instance,由于没有数据报错 synchronized (SingletonClass2.class) { temp = new SingletonClass2(); } instance = temp; } } } return instance; } public void test() { System.out.println("我是:" + this); } }
懒汉模式-内部类
package com.whereta.singleton; /** * Vincent 创建于 2016/4/15. * 该模式是懒汉模式,通过内部类实现线程安全,只有在调用内部类的时候才会加载实例 */ public class SingletonClass3 { //一定要将默认的构造函数设为私有,不能实例化 private SingletonClass3() { } private static class StaticSingletonClass3 { private static SingletonClass3 intance = new SingletonClass3(); } private static SingletonClass3 instance = null; public static SingletonClass3 getInstance() { return StaticSingletonClass3.intance; } public void test() { System.out.println("我是:" + this); } }
测试:
package com.whereta.singleton; import org.freebencher.FbJobResult; import org.freebencher.FbTarget; import org.freebencher.Freebencher; /** * Vincent 创建于 2016/4/15. */ public class Main { public static void main(String[] args) { FbJobResult result = Freebencher.benchmark(new FbTarget() { //the behavior public boolean invoke() { SingletonClass1 singletonClass1 = SingletonClass1.getInstance(); singletonClass1.test(); return true; } }, 20, // concurrency, 10 // number of tests to run ); System.out.println(result.report()); } }
结果:
Connected to the target VM, address: '127.0.0.1:62908', transport: 'socket' Test started. 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 Awaiting termination... 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 我是:com.whereta.singleton.SingletonClass2@1aa0e220 100/100 are done Test completed. Concurrency: 50 Time taken for tests: 31ms Successful tests: 100 Failed tests: 0 Tests per second: 3225.8064516129034 Mean time per test: 0.98ms Percentage of the test finished within a certain time (ms) 50%: 1 60%: 1 70%: 1 80%: 2 90%: 3 95%: 3 98%: 4 99%: 4 100%: 4 Disconnected from the target VM, address: '127.0.0.1:62908', transport: 'socket' Process finished with exit code 0
通过输出:所有对象都是相同的,也就是只有一个实例。
以上三种方式都是线程安全的,可以放心在多线程环境下使用
双重加锁方式代码比较繁琐,不推荐使用,并且在初始化的时候会加锁,一定程度影响效率
饿汉模式是在程序启动的时候就初始化完成,无法是否使用就一直存在,看需求选择是否使用该方式
内部类方式就保证了线程安全,也是一种懒加载模式,代码也比较简洁,推荐
个人博客:http://www.whereta.com