单例模式
Posted chao-zjj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式相关的知识,希望对你有一定的参考价值。
单例模式
一、单例模式介绍
单例模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
二、单例设计模式的八种方式
1)饿汉式(静态常量)
2)饿汉式 (静态代码块)
3)懒汉式(线程不安全)
4)懒汉式(线程安全,同步方法)
5)双重检查
6)静态内部类
7)枚举
三、具体实现
1. 饿汉式(静态常量)
1)创建静态常量实例
2)构造器私有化(防止new)
3)向外暴露一个静态的公共方法。
4)代码实现
/**
* 饿汉式(静态常量)
*/
public class Singleton1
// 1.创建静态常量实例
private final static Singleton1 instance = new Singleton1();
//2. 构造函数私有化
private Singleton1()
//3.获取实例对象
public static Singleton1 getInstance()
return instance;
优缺点说明
1)优点:写法简单,在类装载的时候就完成了实例化。避免了线程同步问题。
2)缺点:在类装载时就完成实例化,没有达到懒加载的效果。如果从始至终从未使用过这个实例,则会造成内存浪费。
2. 饿汉式(静态代码块)
1)静态代码块中,创建单例对象。
2)构造函数私有化
3)提供公有的静态方法,返回实例对象
/**
* 饿汉式(静态常量)
*/
public class SingletonTest2
public static void main(String[] args)
//测试
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1 == instance2); // true
System.out.println("instance1.hashCode=" + instance1.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
class Singleton
// 1.静态代码块中,创建单例对象
private static Singleton instance;
static
instance = new Singleton();
//2. 构造函数私有化
private Singleton()
//3.获取实例对象
public static Singleton getInstance()
return instance;
分析:
1)和饿汉式(静态常量)是一样的,只不过将类实例化的过程放在了静态代码块中。
3、懒汉式(线程不安全)
思路:提供一个静态的公有方法,当使用该方法时,才去创建实例对象
/**
* 懒汉式(线程不安全)
*/
public class SingletonTest3
public static void main(String[] args)
//测试
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1 == instance2); // true
System.out.println("instance1.hashCode=" + instance1.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
class Singleton
private static Singleton instance;
private Singleton()
//3.获取实例对象
public static Singleton getInstance()
if(instance==null)
instance = new Singleton();
return instance;
优缺点说明:
1)起到了懒加载的效果,但只能在单线程下使用。
2)如果在多线程下,一个线程进入了if(instance == null)语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时就会产生多个实例。
3)结论:在实际开发中,不要使用这种方式
4.懒汉式(线程安全,同步方法)
/**
* 懒汉式(线程安全,同步方法)
*/
public class SingletonTest4
public static void main(String[] args)
//测试
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1 == instance2); // true
System.out.println("instance1.hashCode=" + instance1.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
class Singleton
private static Singleton instance;
private Singleton()
//3.获取实例对象
public static synchronized Singleton getInstance()
if(instance==null)
instance = new Singleton();
return instance;
优缺点分析:
1)解决了线程安全问题。
2)方法进行同步效率太低,每个线程想要获得实例时,必须等待其余线程执行完。
3)结论:不推荐使用
5. 双重检查
/**
* 双重检查
*/
public class SingletonTest5
public static void main(String[] args)
//测试
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1 == instance2); // true
System.out.println("instance1.hashCode=" + instance1.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
class Singleton
private static Singleton instance;
private Singleton()
//3.获取实例对象
public static Singleton getInstance()
if(instance==null)
synchronized(Singleton.class)
if(instance == null)
instance = new Singleton();
return instance;
优缺点分析:
1)双重检查概念是多线程开发中经常使用到的,即保证线程安全,又避免反复进行方法同步。
2)线程安全,符合懒加载,效率较高。
3)推荐使用
6. 静态内部类
/**
* 静态内部类
*/
public class SingletonTest6
public static void main(String[] args)
//测试
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1 == instance2); // true
System.out.println("instance1.hashCode=" + instance1.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
class Singleton
private Singleton()
private static class SingletonInstance
public final static Singleton INSTANCE = new Singleton();
public static Singleton getInstance()
return SingletonInstance.INSTANCE;
优缺点分析:
1)采用了类装载机制保证初始化实例时只有一个线程。
2)静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时调用getInstance方法才会装载SingletonInstance类,完成instance实例化。
3)类的静态属性只会在第一次加载类时初始化。JVM帮我们保证了线程的安全性,在类初始化时,别的线程无法进入。
4)推荐使用
7. 枚举
/**
* 枚举
*/
public class SingletonTest7
public static void main(String[] args)
//测试
Singleton instance1 = Singleton.INSTANCE;
Singleton instance2 = Singleton.INSTANCE;
System.out.println(instance1 == instance2); // true
System.out.println("instance1.hashCode=" + instance1.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
enum Singleton
INSTANCE;
优缺点说明:
1)借助枚举实现单例模式。不进避免多线程同步问题,还能防止反序列化重新创建新的对象。
2)推荐使用
四、源码分析
单例模式在JDK应用的源码分析
1)jdk中,java.lang.Runtime就是经典的单例模式(饿汉式)
2)代码分析
五、单例模式注意事项和细节说明
1)单例模式保证了系统内存中该类只存在一个对象,节省了系统资源。对于一些需要频繁创建销毁的对象,单例模式可以提高性能
2)当想实例化一个单例类时,必须使用相应的获取对象的方法,而不是new
3)单例模式使用场景:需要频繁创建和销毁的对象、创建对象耗时过多或资源耗费多(重量级对象)、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂)
以上是关于单例模式的主要内容,如果未能解决你的问题,请参考以下文章