今天算是完完整整把老高的单例模式看了,差不多也懂了,个别不懂的再补吧,下面介绍一下5种单例模式:
饿汉式实现:线程安全,调用效率高。但是,不能延时加载。
懒汉式实现:线程安全,调用效率不高。但是,可以延时加载。
双重检测锁式:由于JVM底层内部模型原因,偶尔会出现问题,不建议使用。
静态内部类式:线程安全,调用效率高,可以延时加载。
枚举式:线程安全,调用效率高。但是,不能延时加载(避免反射和反序列化的漏洞)。
以下先介绍一下5种单例模式:
饿汉式实现:
/**
*单例模式:饿汉模式
*线程安全,调用效率高。但是,不能延时加载
*
* @author cookie
*
*/
public class SingletonDemo01 {
//类初始化时,立刻加载这个对象(没有延时加载的优势)。线程是天然安全
private static SingletonDemo01 instance = new SingletonDemo01();
private SingletonDemo01(){}
//方法没有同步,线程安全,调用效率高。但是,不能延时加载
public static SingletonDemo01 getInstance(){
return instance;
}
}
懒汉式实现:
/**
* 单例模式:懒汉模式
* 线程安全,调用效率不高。但是,可以延时加载
* 真正用的时候才加载,资源利用率高了。
* @author cookie
*
*/
public class SingletonDemo02 {
//类加载时,不初始化对象(延时加载:资源利用率高)
private static SingletonDemo02 instance;
private SingletonDemo02(){}
//synchronized 防止并发量高的时候,出现多个对象
//方法同步,调用效率低,
public static synchronized SingletonDemo02 getInstance(){
if(instance==null){//真正用的时候才加载
instance = new SingletonDemo02();
}
return instance;
}
}
双重检测锁式
/**
* 单例模式:双重检验锁式 结合懒汉式和饿汉式的优点,但由于JVM底层内部模型原因,偶尔会出现问题,不建议使用
*
* @author cookie
*
*/
public class SingletonDemo03 {
private volatile static SingletonDemo03 instance = null;
private SingletonDemo03() {
}
public static SingletonDemo03 getInstance() {
if (instance == null) {
synchronized (SingletonDemo03.class) {// 1
if (instance == null) {// 2
instance = new SingletonDemo03();// 3
}
}
}
return instance;
}
}
静态内部类式
/**
* 单例模式:静态内部类实现单例模式。 优点:线程安全,调用效率高,实现延时加载。
*
* @author cookie
*
*/
public class SingletonDemo04 {
// 类加载时静态内部类不会加载,只有调用getInstance方法时,才会加载(实现延时加载)
private static class SingletonClassInstance {
private final static SingletonDemo04 instance = new SingletonDemo04();
}
private SingletonDemo04() {
}
// 线程安全,方法不同步,调用效率提高
public static SingletonDemo04 getInstance() {
return SingletonClassInstance.instance;
}
}
枚举式:
/**
* 单例模式:枚举类型实现单例模式 线程安全,调用效率高。但是,不能延时加载 避免反射和反序列化的漏洞
*
* @author cookie
*
*/
public enum SingletonDemo05 {
INSTANCE;// 这个枚举元素,本身就是单例模式
// 添加自己需要的操作
public void singletonOperation() {
}
}
下面是测试5种单例模式的效率:
/**
*
* 描述:多线程环境下五种单例模式的效率
* @author cookie
*/
public class Client2 {
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
int threadNum = 10;
final CountDownLatch countDownLatch = new CountDownLatch(threadNum);
//10个线程
for (int i = 0; i < threadNum; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
SingletonDemo05 s1 = SingletonDemo05.INSTANCE;
}
countDownLatch.countDown();//计数器减一
}
}).start();
}
countDownLatch.await();//main线程阻塞,等待计数器为0,即threadNum = 0;
long end = System.currentTimeMillis();
System.out.println("总耗时:"+(end-start));
}
}
实现结果如下:
| 单例模式 | 总耗时 |
| 饿汉式 | 13 |
| 懒汉式 | 547 |
| 双重检测锁式 | 20 |
| 静态内部类式 | 17 |
| 枚举式 | 13 |
选用时,
单例对象,占用资源少,无需延时加载,枚举式 优于 饿汉式
单例对象,占用资源多,需要延时加载,静态内部类式 优于 懒汉式
原文:http://www.cnblogs.com/blogofcookie/p/5793865.html