一.说明
1.属于创建者模式
2.Singleton Pattern
3.设计到一个单一的类,负责创建自己的对象,确保只有单个对象被创建
4.提供一种访问唯一对象的方式
5.实现思路
a.私有化构造方法
b.创建对象
c.提供公共方法获取对象
二.实现分类
1.饿汉式:类加载就创建类单例对象
2.懒汉式:类加载不创建单例对象,首次使用才创建
三.饿汉式实现
1.静态变量
package com.learning.singleton;
public class Static_Variable_Singleton {
private Static_Variable_Singleton(){}
private static Static_Variable_Singleton singleton = new Static_Variable_Singleton();
public static Static_Variable_Singleton getInstance(){
return singleton;
}
public static void main(String[] args) {
Static_Variable_Singleton instance1 = Static_Variable_Singleton.getInstance();
Static_Variable_Singleton instance2 = Static_Variable_Singleton.getInstance();
System.out.println(instance1 == instance2);
}
}
2.静态代码块
package com.learning.singleton;
public class Static_Block_Singleton {
private static Static_Block_Singleton singleton;
private Static_Block_Singleton(){}
static {
singleton = new Static_Block_Singleton();
}
public static Static_Block_Singleton getInstance(){
return singleton;
}
public static void main(String[] args) {
Static_Block_Singleton instance1 = Static_Block_Singleton.getInstance();
Static_Block_Singleton instance2 = Static_Block_Singleton.getInstance();
System.out.println(instance1 == instance2);
}
}
3.枚举方式
- 枚举类实现单例模式是极力推荐的单例实现模式,因为枚举类型是线程安全的,只会装载一次,设计者充分利用了枚举的这个特性来实现单例模式,枚举类型是所用单例实现中唯一一种不会被破坏的单例实现模式。
package com.learning.singleton;
public enum Enum_Singleton {
INSTANCE;
public static void main(String[] args) {
Enum_Singleton instance1 = Enum_Singleton.INSTANCE;
Enum_Singleton instance2 = Enum_Singleton.INSTANCE;
System.out.println(instance1 == instance2);
}
}
四.懒汉式实现
1.线程不安全的懒汉式
package com.learning.singleton;
public class Lazy_Singleton_Not_Safe {
private Lazy_Singleton_Not_Safe(){}
private static Lazy_Singleton_Not_Safe singleton;
public static Lazy_Singleton_Not_Safe getInstance(){
if(singleton == null){
singleton = new Lazy_Singleton_Not_Safe();
}
return singleton;
}
public static void main(String[] args) throws InterruptedException {
Lazy_Singleton_Not_Safe instance1 = Lazy_Singleton_Not_Safe.getInstance();
Lazy_Singleton_Not_Safe instance2 = Lazy_Singleton_Not_Safe.getInstance();
System.out.println(instance1 == instance2);
}
}
2.线程安全的懒汉式
package com.learning.singleton;
public class Lazy_Singleton_Safe {
private Lazy_Singleton_Safe(){}
private static Lazy_Singleton_Safe singleton;
public static synchronized Lazy_Singleton_Safe getInstance(){
if(singleton == null){
singleton = new Lazy_Singleton_Safe();
}
return singleton;
}
public static void main(String[] args) throws InterruptedException {
Lazy_Singleton_Safe instance1 = Lazy_Singleton_Safe.getInstance();
Lazy_Singleton_Safe instance2 = Lazy_Singleton_Safe.getInstance();
System.out.println(instance1 == instance2);
}
}
3.线程安全效率高的懒汉式(双重检查锁)
package com.learning.singleton;
public class Lazy_Singleton_Double_Check_Lock {
private Lazy_Singleton_Double_Check_Lock(){}
private static volatile Lazy_Singleton_Double_Check_Lock singleton;
public static Lazy_Singleton_Double_Check_Lock getInstance(){
if(singleton == null){
synchronized (Lazy_Singleton_Double_Check_Lock.class){
if(singleton == null){
singleton = new Lazy_Singleton_Double_Check_Lock();
}
}
}
return singleton;
}
public static void main(String[] args) throws InterruptedException {
Lazy_Singleton_Double_Check_Lock instance1 = Lazy_Singleton_Double_Check_Lock.getInstance();
Lazy_Singleton_Double_Check_Lock instance2 = Lazy_Singleton_Double_Check_Lock.getInstance();
System.out.println(instance1 == instance2);
}
}
4.静态内部类
- jvm在加载外部类的过程中,是不会加载静态内部类的,只有内部类的属性/方法被调用时才会被加载,并初始化其静态属性。静态属性被static修饰,保证只被实例化一次,严格保证实例化顺序
- 静态内部类单例模式是开源项目常见的一种单例模式。在没有加任何锁的情况下,保证了多线程下的安全,没有任何性能影响和空间的浪费。
package com.learning.singleton;
public class Lazy_Static_Inner_Class {
private Lazy_Static_Inner_Class(){}
private static class Static_Inner_Class{
private static Lazy_Static_Inner_Class instance = new Lazy_Static_Inner_Class();
}
public static Lazy_Static_Inner_Class getInstance(){
return Static_Inner_Class.instance;
}
public static void main(String[] args) {
Lazy_Static_Inner_Class instance1 = Lazy_Static_Inner_Class.getInstance();
Lazy_Static_Inner_Class instance2 = Lazy_Static_Inner_Class.getInstance();
System.out.println(instance1 == instance2);
}
}