Java單例模式的實現


單例的實現

單例設計模式的問題

1.      線程安全問題用synchronized修飾實例化部分代碼

2.      性能問題–采用懶漢式實例化

3.      指令重排序問題–用volatile修飾實例

4.      反序列化攻擊問題–構造函數判斷存在實例時拋異常

5.      反射攻擊問題–增加readResolve方法

6.      不符合開閉原則,需要改代碼

五種單例實現方式

1.   餓漢式

package me.muphy.singleton;

import java.io.Serializable;

/**
* 2019/4/1
* 莫非
*/
public class HungrySingleton implements Serializable{

   private static final HungrySingleton hungrySingleton = new HungrySingleton();

   private HungrySingleton() {

   }

   public static HungrySingleton getInstance() {
       return hungrySingleton;
   }

   private ObjectreadResolve() {
       return hungrySingleton;
   }

}

2.   懶漢式延時加載方式

package me.muphy.singleton;

/**
 * 2019/4/1
 * 莫非
 */
public class LazySingleton {

    private volatile static LazySingleton lazySingleton = null;

    private LazySingleton() {
        if (lazySingleton != null) {
            throw new RuntimeException("此類以單例存在!");
        }
    }

    public static LazySingleton getInstance() throws Exception {
        if (lazySingleton == null) {
            synchronized (LazySingleton.class) {
                if (lazySingleton == null) {
                    lazySingleton = new LazySingleton();
                }
            }
        }
        return lazySingleton;
    }

    private Object readResolve() {
        return lazySingleton;
    }

}

3.   懶漢式  內部內實現單例

package me.muphy.singleton;

/**
 * 2019/4/1
 * 莫非
 */
public class LazyJvmSingleton {

    private LazyJvmSingleton(){

    }

    public static LazyJvmSingleton getInstance(){
        return LazySingleton.lazyJvmSingleton;
    }

    private static class LazySingleton{
        public static final LazyJvmSingleton lazyJvmSingleton = new LazyJvmSingleton();
    }

    private Object readResolve(){
        return LazySingleton.lazyJvmSingleton;
    }
}

4.   注冊式  枚舉式單例

package me.muphy.singleton;

/**
 * 2019/4/1
 * 莫非
 */
public enum EnumSingleton {
    INSTANCE;

    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static EnumSingleton getInstance() {
        return INSTANCE;
    }
}

5.   注冊式  容器式單例

package me.muphy.singleton;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 2019/4/1
 * 莫非
 */
public class ContainerSingleton {
    private ContainerSingleton() {
    }

    private static Map<String, Object> ioc = new ConcurrentHashMap<>();

    public static Object getBean(String className) {
        synchronized (ioc) {
            if (!ioc.containsKey(className)) {
                try {
                    Object obj = Class.forName(className).newInstance();
                    ioc.put(className, obj);
                    return obj;
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                }
            }
        }

        return ioc.get(className);
    }
}

線程內部的單例

線程內部的單例采用注冊式單例,是偽線程安全的,可用來實現多數據源切換

package me.muphy.singleton;

/**
 * 2019/4/2
 * 莫非
 */
public class ThreadLocalSingleton {

    private ThreadLocalSingleton() {
    }

    private static final ThreadLocal<ThreadLocalSingleton> threadLocalInstance =
            new ThreadLocal<ThreadLocalSingleton>() {

                @Override
                protected ThreadLocalSingleton initialValue() {
                    return new ThreadLocalSingleton();
                }
            };

    public static ThreadLocalSingleton getInstance() {
        return threadLocalInstance.get();
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM