1,单例模式
解法一:只适用于单线程:
package com.singleton; import sun.security.jca.GetInstance.Instance; public class Singleton1 { private static Singleton1 instance = null; public Singleton1() { } public static Singleton1 getInstance() { if (instance == null) { instance = new Singleton1(); } return instance; } public static void main(String[] args) { // TODO Auto-generated method stub Singleton1 s1 = getInstance(); Singleton1 s2 = getInstance(); System.out.println(s1==s2); } }
解法二:适用于多线程但效率不高----在getInstance()上加synchronized加锁
package com.singleton; public class Singleton1 { private static Singleton1 instance = null; public Singleton1() { } public static synchronized Singleton1 getInstance() { if (instance == null) { instance = new Singleton1(); } return instance; } public static void main(String[] args) { // TODO Auto-generated method stub Singleton1 s1 = getInstance(); Singleton1 s2 = getInstance(); System.out.println(s1==s2); } }
解法三:改进的多线程单例----不需要整个方法加锁,只需要创建时加锁
package com.singleton; public class Singleton1 { private static Object lock = new Object(); private static Singleton1 instance = null; public Singleton1() { } public static Singleton1 getInstance() { if (instance == null) { synchronized (lock) { if (instance == null) { instance = new Singleton1(); } } } return instance; } public static void main(String[] args) { // TODO Auto-generated method stub Singleton1 s1 = getInstance(); Singleton1 s2 = getInstance(); System.out.println(s1==s2); } }
解法四(强烈推荐):利用静态构造函数
package com.singleton; public class Singleton2 { private static Singleton2 instance = new Singleton2(); public static Singleton2 getInstance() { return instance; } public static void main(String[] args) { // TODO Auto-generated method stub Singleton2 s1 = getInstance(); Singleton2 s2 = getInstance(); System.out.println(s1 == s2); } }
原理:类成员变量只在类加载时初始化一次。
解法五(强烈推荐):
package com.singleton; public class Singleton3 { private static class SingletonHolder { private final static Singleton3 instance = new Singleton3(); } public Singleton3() { } public static Singleton3 getInstance() { return SingletonHolder.instance; } public static void main(String[] args) { Singleton3 s1 = getInstance(); Singleton3 s2 = getInstance(); System.out.println(s1 == s2); } }
因为SingletonHolder内部类只有在显式被调用时才会加载,所以只有在调用getInstance方法时才会实例化instance,这样就解决了解法四加载过早的问题。