拥有独立且唯一的对象

这次讲述的是单件模式,就是整个内容里只有一个实例化“唯一”对象。这么说可能有点拗口,这么说吧,比方说,线程池,缓存,注册表,日志文件,甚至做JDBC中连接,关闭,增删改查数据库的Connection类(个人命名也许并不一样)、工具类等等。这些东西往往是要实例一次,就能在整个项目中使用了。

单件模式并不难理解定义如下
单件模式:确保一个类中只有一个实例,并提供一个全局访问点。
是的就这么一句话的定义。一般单件模式分为“懒汉式”和“饿汉式”做法

直接上代码。

“懒汉式”做法

package singleton01;

public class Singleton01 {
    // 利用一个静态变量记录本类当中唯一的实例(mySingleton01)
    private  static Singleton01 mySingleton01 = null;

    public Singleton01() {
    }

    // synchronized关键字:线程同步锁,在多线程中去互斥地访问临界资源
    // 迫使每个线程在进入方法之前,要先等别的线程执行完离开方法后才能执行,达到多个线程排队,不会造成有多个线程同时进入这个方法
    // 即是同步。但同步会使程序效率降低
    public static synchronized Singleton01 getInstance() {
        if (mySingleton01 == null) {
            mySingleton01 = new Singleton01();
            System.out.println("Singleton01被实例化了");
        }
        System.out.println("返回Singleton01实例");
        return mySingleton01;
    }
    /**
     * 上面方法就是常说了“懒汉式”做法,大体意思就是当谁需要类方法时采取实例化
     */
}
package singleton01;

public class TestMain {
    public static void main(String[] args) {
        // 打印出前两行结果
        Singleton01 singleton01 = Singleton01.getInstance();

        // 此时我们看到第二次调用类方法时候,没有去实例对象
        // 这里涉及并发方面问题,暂时没学习并发,具体怎么个原理我也不知道...
        Singleton01 singleton02 = Singleton01.getInstance();
    }
}

效果图1
图片描述

效果图2
图片描述

之前的做法中我们用到了synchronized,就是为了防止线程启动的随机性找出变量混乱,我这个小例子可能看不出来什么。但实际上同步线程(synchronized)会使得程序效率大幅降低。利用双重检查加锁可以有效解决此问题,

使用双重检查加锁

package singleton01;

public class singleton02 {
    // 利用双重检查加锁,先检查实例是否已经创建,如果没创建,就进行同步。
    // volatile:instance变量被初始化singleton02实例时,多个线程会正确处理instance变量
    // 线程是具有随机性的,与程序执行顺序无关。
    private volatile static singleton02 instance=null;

    public singleton02() {        
    }

    public static singleton02 getInstance() {
        if (instance == null) {
            // 检查实例,不存在的话进入同步区域,只有第一次才执行这里
            synchronized (singleton02.class) {
                System.out.println("进入同步区域");
                if (instance == null) {
                    System.out.println("instance被实例化了");
                    instance = new singleton02();
                }
            }
        }
        System.out.println("返回instance实例");
        return instance;
    }
}
package singleton01;

public class TestMain02 {
    public static void main(String[] args) {
        //第一次进入方法会进入同步区实例化
        singleton02 singleton02 = null;
        singleton02 = singleton02.getInstance();
        
        //当第二次进入时,已有实例,不会同步了,直接返回实例.
        singleton02 singleton03 = null;
        singleton03 = singleton02.getInstance();    
    }

}

效果图
图片描述

"饿汉式"做法

package singleton02;

public class Singleton {
    /**
     * “饿汉式”:加载这个类时立刻创建本类中唯一的单件实例,
     */
    private static Singleton uniqueInstance = new Singleton();

    private Singleton() {

    }

    public static Singleton getInstance() {
        System.out.println("返回实例实例");
        return uniqueInstance;
    }
}
package singleton02;

public class TestMain {
    public static void main(String[] args) {
        //直接返回实例
        Singleton singleton = Singleton.getInstance();
    }
}

效果图
图片描述

注:双重检查加锁不适用与1.4之前的java版本。

要点:
1、单件模式确保程序中一个类最多只有一个实例。
2、单件模式提供这个实例的全局访问点。
3、实现单件模式,需要私有构造器,一个静态方法,一个静态变量。
4、设计到多线程问题,同步会降低程序效率。

感谢你看到这里,至此单件模式内容结束,本人文笔随便,若有不足或错误之处望给予指点,90度弯腰~~~很快我会发布下一个设计模式内容,生命不息,编程不止!

参考书籍:《Head First 设计模式》

暖心先森
287 声望16 粉丝

生命不息,编程不止!