1.介绍
单例模式,是23中设计模式中比较重要的设计模式,单例其实就是单一实例,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。
java中的RunTime类就使用了单例模式
2.写法
1)饿汉式
- public class Singleton {
- /**
- * 1)构造器私有化
- * 2)自行创建,并且用静态变量保存
- * 3)对外提供这个实例
- * 4)强掉这是一个单例,我们可以用final修饰
- */
- public static final Singleton INSTANCE = new Singleton();
- private Singleton(){
- }
- }
-
- public class MainTest {
- public static void main(String[] args) {
- Singleton instance=Singleton.INSTANCE;
- Singleton instance1 = Singleton.INSTANCE;
- System.out.println(instance);
- System.out.println(instance1);
- }
- }
-
- //控制台输出
- cn.nlg.test.Singleton@1540e19d
- cn.nlg.test.Singleton@1540e19d
特点:
a)在这个类初始化时就创建了对象, 每次调用都返回同一个对象
b)如果没有使用到这个对象会浪费内存空间
2)懒汉式
- public class Singleton {
-
- private static Singleton instance = null;
-
- private Singleton() {
- }
-
- //这里多线程环境下会有线程安全问题,单线程没问题
- public static Singleton getInstance() {
- if(instance == null){
- instance =new Singleton();
- }
- return instance;
- }
-
- }
-
- public class MainTest {
- public static void main(String[] args) {
- Singleton instance=Singleton.getInstance();
- Singleton instance1 = Singleton.getInstance();
- System.out.println(instance);
- System.out.println(instance1);
- }
- }
-
- //控制台输出
- cn.nlg.test.Singleton@1540e19d
- cn.nlg.test.Singleton@1540e19d
-
-
-
-
特点: 多线程的环境下会存在线程安全问题,这个适用于单线程
3)双检锁
- class Singleton {
- public volatile static Singleton instance = null;
-
- public Singleton(){ }
-
-
- public static Singleton getInstance(){
- //外层判断是为了让instance不为空时无需等待
- if(instance == null){
- //使用synchronized关键字,保证了每次只有一个线程操作
- synchronized (Singleton.class){
- if(instance == null){
- instance = new Singleton();
- }
- }
- }
- return instance;
- }
-
- }
- //主方法测试
- public class MainTest {
- public static void main(String[] args) {
- Singleton instance=Singleton.getInstance();
- Singleton instance1 = Singleton.getInstance();
- System.out.println(instance);
- System.out.println(instance1);
- }
- }
- //控制台输出
- cn.nlg.test.Singleton@1540e19d
- cn.nlg.test.Singleton@1540e19d
-
特点:1)解决了线程安全问题
b)volatile是为了防止指令重排,可以去了解一下volatile关键字的作用
4)静态内部类
- public class Singleton{
- private Singleton(){}
- //静态内部类
- private static class Inner{
- private static Singleton INSTANCE = new Singleton();
- }
-
- public static Singleton getInstance(){
- return Inner.INSTANCE;
- }
- }
-
- //主方法测试
- public class MainTest {
- public static void main(String[] args) {
- Singleton instance=Singleton.getInstance();
- Singleton instance1 = Singleton.getInstance();
- System.out.println(instance);
- System.out.println(instance1);
- }
- }
- //控制台输出
- cn.nlg.test.Singleton@1540e19d
- cn.nlg.test.Singleton@1540e19d
特点:a)这是懒汉式中比较推荐的写法
b)外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE
5)枚举
- public enum Singleton {
- INSTANCE;
- }
- //主方法测试
- public class MainTest {
- public static void main(String[] args) {
- Singleton instance=Singleton.INSTANCE;
- Singleton instance1 =Singleton.INSTANCE;
- System.out.println(instance);
- System.out.println(instance1);
- }
- }
- 重写了toString方法,控制台输出
- INSTANCE
- INSTANCE
特点 :a) enum 类型是线程安全的,因为Java 类的加载和初始化过程都是线程安全的(反编译一下枚举类)
b)饿汉式中比较推荐的写法
例子:
枚举类:
- public enum T {
- SPRING,SUMMER,AUTUMN,WINTER;
- }
反编译之后的枚举类:
- public final class T extends Enum
- {
- //省略部分内容
- public static final T SPRING;
- public static final T SUMMER;
- public static final T AUTUMN;
- public static final T WINTER;
- private static final T ENUM$VALUES[];枚举类型和泛型 < 228
- static
- {
- SPRING = new T("SPRING", 0);
- SUMMER = new T("SUMMER", 1);
- AUTUMN = new T("AUTUMN", 2);
- WINTER = new T("WINTER", 3);
- ENUM$VALUES = (new T[] {
- SPRING, SUMMER, AUTUMN, WINTER
- });
- }
- }
1.枚举类型T不可被继承
2.T中所有属性都被 static final 修饰