单例设计模式8种实现方式
1)饿汉式(静态变量)
实现步骤:
1、构造器私有化
2、内部创建对象实例
3、提供一个公有静态方法,返回实例对象
public class SingletonTest01 {
public static void main(String[] args) {
Singleton singleton1 = Singleton.getInstance();
System.out.println(singleton1);
}
}
//饿汉式(静态变量)
class Singleton{
//1、构造器私有化
private Singleton(){}
//2、内部创建对象实例
public final static Singleton instance = new Singleton();
//3、提供一个公有静态方法,返回实例对象
public static Singleton getInstance(){
return instance;
}
}
优点:在类装载的时候就完成了实例化,避免了线程同步的问题
缺点:没有达到懒加载的效果,如果一开始就没有用到这个实例,则会造成资源浪费
2)饿汉式(静态代码块)
public class SingletonTest02 {
public static void main(String[] args) {
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
System.out.println(singleton1);
System.out.println(singleton2);
System.out.println("singleton1.hashCode():"+singleton1.hashCode());
System.out.println("singleton1.hashCode():"+singleton2.hashCode());
}
}
//饿汉式(静态代码块)
class Singleton{
//1、构造器私有化
private Singleton(){}
//2、内部创建对象实例
public static Singleton instance;
static {//在静态代码块中创建对象
instance = new Singleton();
}
//3、提供一个公有静态方法,返回实例对象
public static Singleton getInstance(){
return instance;
}
}
优缺点:与饿汉式(静态变量)类似
3)懒汉式(线程不安全)
//懒汉式(线程不安全)
class Singleton{
//1、构造器私有化
private Singleton(){}
//2、声明对象实例
public static Singleton instance;
//3、提供一个公有静态方法,使用到该方法时才创建对象
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
优缺点:
1、起到了懒加载的效果
2、在多线程的环境下有可能有多个线程同时进入if语句,创建出多个实例
4)懒汉式(线程安全,同步方法)
//懒汉式(线程安全)
class Singleton{
//1、构造器私有化
private Singleton(){}
//2、声明对象实例
public static Singleton instance;
//3、提供一个公有静态方法,加入同步处理的关键字,解决线程完全问题
public synchronized static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
优缺点:
1、解决了线程安全的问题
2、在多线程环境下,每个线程想获得类的实例对象的时候,都要排队执行getInstance()方法。而其实getInstance()方法只执行一次就够了,后面想获得类的实例直接return就行了
3、方法进行同步,效率太低
5)懒汉式(线程不安全,同步代码块)
//懒汉式(线程不安全)
class Singleton{
//1、构造器私有化
private Singleton(){}
//2、声明对象实例
public static Singleton instance;
//3、提供一个公有静态方法,加入同步处理的同步代码块
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
instance = new Singleton();
}
}
return instance;
}
}
优缺点:不能起到同步的作用,实际开发中,不能使用这种方法
6)双重检查
volatile关键的作用:将变量立即更新到主存
//双重检查
class Singleton{
//1、构造器私有化
private Singleton(){}
//2、声明对象实例
public static volatile Singleton instance;
//3、提供一个公有静态方法,加入双重检查代码,解决线程安全问题,同时解决懒加载问题
public static Singleton getInstance(){
if(instance == null){
synchronized (Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
优缺点:线程安全,延迟加载(懒加载),效率较高,推荐使用
7)静态内部类
静态内部类的特点:
1、当外部类被加载的时候,静态内部类是不会被加载的
2、静态内部类被加载的时候线程是安全的
//静态内部类
class Singleton{
//构造器私有化
private Singleton(){}
//写一个静态内部类,该类中有一个静态属性Singleton
private static class SingletonInstance{
private static final Singleton INSTANCE = new Singleton();
}
//提供一个公有静态方法,直接返回SingletonInstance.INSTANCE
public static Singleton getInstance(){
return SingletonInstance.INSTANCE;
}
}
推荐使用
8)枚举
public class SingletonTest08 {
public static void main(String[] args) {
Singleton singleton1 = Singleton.INSTANCE;
Singleton singleton2 = Singleton.INSTANCE;
System.out.println(singleton1==singleton2);
System.out.println("singleton1.hashCode():"+singleton1.hashCode());
System.out.println("singleton1.hashCode():"+singleton2.hashCode());
singleton1.sayOK();
}
}
//枚举可以实现单例
enum Singleton{
INSTANCE;//属性
public void sayOK(){
System.out.println("ok");
}
}
推荐使用
总结:
1、单线程可以使用(但会造成资源浪费):
1)饿汉式(静态变量)
2)饿汉式(静态代码块)
2、在单线程或多线程环境下推荐使用:
6)双重检查
7)静态内部类
8)枚举