首页 » JAVA » java单例模式饿汉式与懒汉式的区别

java单例模式饿汉式与懒汉式的区别

 

假如文章若有错误之处,请多多谅解,希望指出错误之处.


单例模式介绍


单例从字面意思上来看,就是要保证任务当中只能有一个唯一对像,就像是windows系统中的任务管理器,不管你打开几个任务,他都只会有一个窗口.玩过LOL的都知道,人多的时候需要排队才能进行登入,这样的行为在单例中也可以理解成把登陆的用户放到内存当中,登入成功内存减1,新进登入用户内存加1,一个一个排队,有效的保证数据维一性.

设计模式一共有23种,单例模式也是设计模式当中常用的模式之一.

单例模式分为两种:饿汉式与懒汉式.举个例子.

懒汉式:使用最简单,线程不安全.

/**
 * java单例模式饿汉式与懒汉式的区别
 * www.vuvps.com
 */
public class TestSingleton {

    private static TestSingleton singleton = null;

    //原则问题,禁止外部创建。
    private TestSingleton() {
    }

    public static TestSingleton getInstance() {
        if (singleton == null) {
            singleton = new TestSingleton();
        }
        return singleton;
    }

    public void test(){
        //todo......
    }
}

调用方式:

public static void main(String[] args) {
   TestSingleton.getInstance().test();
}

上面提到了,线程不安全,同时上百个线程访问这个类的同一份数据并进行操作时,就会导致数据不一致.

解决方法,使用synchronized加锁,让线程同步,避免数据错误.

/**
 * java单例模式饿汉式与懒汉式的区别
 * www.vuvps.com
 */
public class TestSingleton {

    private static TestSingleton singleton = null;

    //原则问题,禁止外部创建。
    private TestSingleton() {
    }

    public static TestSingleton getInstance() {
        if (singleton == null) {
            synchronized (TestSingleton.class) {
                if (singleton == null) {
                    singleton = new TestSingleton();
                }
            }
        }
        return singleton;
    }
 }

上面的代码的意思就是:两个线程同时访问getInstance()方法,线程1进地入getInstance()中当判断实例是不是空的,true就实例化;当线程2也进入到getInstance()当中的时候,由于线程1已经执行到了第二个synchronized关键字内部,就会使线程2被锁在外面,线程1结束后并实例化之后,线程2才会执行第二个实例判断.这个时候由于TestSingleton 已经被实例化了,线程2也就会直接返回线程1创建的实例.


饿汉式单例模式:

/**
 * java单例模式饿汉式与懒汉式的区别
 * www.vuvps.com
 */
public class TestSingleton {

    private static final TestSingleton singleton = new TestSingleton();
    private int i = 0;

    //原则问题,禁止外部创建。
    private TestSingleton() {
    }

    public static TestSingleton getInstance() {
        return singleton;
    }
}

这种饿汉式单例模式,创建是非常的简单了,TestSingleton已经被声明成static和final了,类在加载的时候就已经被实例化了,提前占用了系统资料,这种方式创建本身也就是线程安全的.

假如这种饿汉式单例模式是完美的话,也就没有什么双重加锁之类的线程安全解决方法了.它的缺陷在于它不是懒加载模式,它会在类一开始加载就会初始化.导致那些需要通过getInstance()传参调用进行操作的类也就无法使用这种方式创建了.

原文链接:java单例模式饿汉式与懒汉式的区别,转载请注明来源!

0