单例模式有三种:
-
饿汉模式:提前初始化好对象,需要的时候直接调用
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@1aa0e220Awaiting 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@1aa0e220100/100 are doneTest completed.Concurrency: 50Time taken for tests: 31msSuccessful tests: 100Failed tests: 0Tests per second: 3225.8064516129034Mean time per test: 0.98msPercentage of the test finished within a certain time (ms)50%: 160%: 170%: 180%: 290%: 395%: 398%: 499%: 4100%: 4Disconnected from the target VM, address: '127.0.0.1:62908', transport: 'socket'Process finished with exit code 0
通过输出:所有对象都是相同的,也就是只有一个实例。
以上三种方式都是线程安全的,可以放心在多线程环境下使用
-
双重加锁方式代码比较繁琐,不推荐使用,并且在初始化的时候会加锁,一定程度影响效率
-
饿汉模式是在程序启动的时候就初始化完成,无法是否使用就一直存在,看需求选择是否使用该方式
-
内部类方式就保证了线程安全,也是一种懒加载模式,代码也比较简洁,推荐
个人博客: