天天看点

java懒汉模式_单例中懒汉和恶汉模式的区别【Java面试题】

(1)问题分析:

主要考察懒汉和饿汉模式在创建时的区别以及分别在什么情况下使用懒汉模式,什么情况下使用饿汉模式。

懒汉模式:在类加载的时候不被初始化。

饿汉模式:在类加载时就完成了初始化,但是加载比较慢,获取对象比较快。

饿汉模式是线程安全的,在类创建好一个静态对象提供给系统使用,懒汉模式在创建对象时不加上synchronized,会导致对象的访问不是线程安全的。

(2)核心答案讲解:

饿汉式:

public class Singleton{

​ private static Singleton singleton = new Singleton ();

​ private Singleton (){}

​ public static Singleton getInstance(){return singletion;}

​ }

懒汉式:

public class Singleton{

​ private static Singleton singleton = null;

​ public static synchronized synchronized getInstance(){

​ if(singleton==null){

​ singleton = new Singleton();

​ }

​ return singleton;

​ }

​ }

饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变

懒汉式如果在创建实例对象时不加上synchronized则会导致对对象的访问不是线程安全的。

从实现方式来讲他们最大的区别就是懒汉式是延时加载,是在需要的时候才创建对象,而饿汉式在虚拟机启动的时候就会创建。

(3)问题扩展

懒汉式不会预先创建对象,只在第一次调用时才创建对象,但是多线程并发执行的时候就很容易出现安全隐患,比如说第一个线程在判断newInstance == null时,还没有new出实例时,第二个线程也进来,判断的newInstance也是null,然后也会new出实例,这就不符合单例模式了, 所以需要加锁。使用synchronized关键字加锁能解决安全问题,但是加锁同时会出现一个问题,那就是每次都需要判断锁,这样性能就会降低,所以为了提高性能,我们应该尽量减少锁判断的次数,加上双重判断。

//静态工厂方法、单锁

public synchronized static SingletonTest2 getInstance1(){

​ if (single2==null) {

​ single2 = new SingletonTest2();

​ }

​ return single2;

}

//静态工厂方法、双重锁

public static SingletonTest2 getInstance2(){

​ if (single2==null) {

​ synchronized (SingletonTest2.class) {

​ if (single2==null) {

​ single2 = new SingletonTest2();

​ }

​ }

​ }

​ return single2;

}

(4)结合项目中的使用

懒汉式的特点是延迟加载,比如配置文件,采用懒汉式的方法。

猜你喜欢