反射与单例设计模式 | 带你学《Java语言高级特性》之八十四

上一篇:反射与工厂设计模式 | 带你学《Java语言高级特性》之八十三
【本节目标】
通过案例引出懒汉式的单例设计模式所出现的问题,并使用使用synchronized关键字来处理解决。

反射与单例设计模式

单例设计模式的核心本质在于:类内部的构造方法私有化,在类的内部产生实例化对象后通过static方法获取实例化对象,进行类中的结构调用,单例设计模式一共有两类:懒汉式、饿汉式,本节主要来讨论懒汉式的单例设计模式。

范例:观察懒汉式单例设计模式的问题
单线程状态执行:

public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
        Singleton sinA = Singleton.getInstance();
        sinA.print();
    }
}
class Singleton {
    private static Singleton instance = null;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    public void print() {
        System.out.println("www.mldn.cn");
    }
}

多线程状态执行:

public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
        for (int x = 0; x < 3; x++) {
            new Thread(()->{
                Singleton.getInstance().print();
            },"单例消费端-"+ x).start();
        }
        /**
         * 【单例消费端-0】****** 实例化Singleton类对象 *******
         * 【单例消费端-1】****** 实例化Singleton类对象 *******
         * www.mldn.cn
         * 【单例消费端-2】****** 实例化Singleton类对象 *******
         * www.mldn.cn
         * www.mldn.cn
         */
    }
}
class Singleton {
    private static Singleton instance = null;
    private Singleton() {
        System.out.println("【" + Thread.currentThread().getName() +"】****** 实例化Singleton类对象 *******",Thread.currentThread().getName());
    }
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    public void print() {
        System.out.println("www.mldn.cn");
    }
}

单例设计模式的最大特点是在整体的运行程序中只允许产生一个实例化对象,但当有了若干个线程之后,实际上当前的程序就会产生多个实例化对象了,此时就不是单例设计模式了。此时问题造成的关键在于代码本身出现了不同步的情况,而要想解决的关键就在于同步处理,也就是需要使用synchronized关键字。

反射与单例设计模式 | 带你学《Java语言高级特性》之八十四
单例设计模式问题

范例:修改getInstance()进行同步处理

class Singleton {
    private static Singleton instance = null;
    private Singleton() {
        System.out.println("【" + Thread.currentThread().getName() +"】****** 实例化Singleton类对象 *******",Thread.currentThread().getName());
    }
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    public void print() {
        System.out.println("www.mldn.cn");
    }
}

这个时候的确是进行了同步处理,但这个同步处理的代价有些大,因为效率会低。因为整体代码中实际上只有一块部分需要进行同步处理,也就是instance对象的实例化处理部分。我们可以知道,之前的同步操作是有些失误的。

范例:更加合理地进行同步处理

class Singleton {
    private static volatile Singleton instance = null;
    private Singleton() {
        System.out.printf("【" + Thread.currentThread().getName() +"】****** 实例化Singleton类对象 *******",Thread.currentThread().getName());
    }
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
    public void print() {
        System.out.println("www.mldn.cn");
    }
}

面试题:请编写单例设计模式
直接编写一个饿汉式的单例设计模式,并且实现构造方法私有化;
在Java中哪里使用到了单例设计模式?
Runtime类、Pattern类、Spring框架;
懒汉式单例模式的问题
即上面描述所出现的问题。
单例设计模式的最大特点是在整体的运行程序中只允许产生一个实例化对象,但当有了若干个线程之后,实际上当前的程序就会产生多个实例化对象了,此时就不是单例设计模式了。此时问题造成的关键在于代码本身出现了不同步的情况,而要想解决的关键就在于同步处理,也就是需要使用synchronized关键字。

想学习更多的Java的课程吗?从小白到大神,从入门到精通,更多精彩不容错过!免费为您提供更多的学习资源。
本内容视频来源于阿里云大学

下一篇:反射获取类结构信息 | 带你学《Java语言高级特性》之八十五
更多Java面向对象编程文章查看此处

上一篇:设计模式之美:Chain of Responsibility(职责链)


下一篇:Autotestplat