单例模式定义:Ensure a class has only one instance,and provide a global point of access to it.(确保某一个类只有一个实例,自行实例化并提供一个全局访问点)
实现一:
对getInstance()方法进行同步 ,线程安全,影响性能
public class Singleton { private static Singleton instance = null; private Singleton(){} public synchronized static Singleton getInstance(){ if(null == instance){ instance = new Singleton(); } return instance; } }
public class Singleton { private static Singleton instance = null; private Singleton(){} public static Singleton getInstance(){ synchronized(Singleton.class){ if(null == instance){ instance = new Singleton(); } return instance; } } }
实现二:
这种实现方式的问题是单例对象是在类初始化时完成初始化,如果单例对象的创建需要消耗较多的资源,创建完成后又不立即使用,将造成系统资源严重浪费
public class Singleton { private static Singleton instance = new Singleton(); //private final static Singleton instance = new Singleton();也是可以的 private Singleton(){} public static Singleton getInstance(){ return instance; } }
instance的创建过程是线程安全的,详见:http://blog.csdn.net/a19881029/article/details/17068191
实现三(这种实现方式被称为Initialization on demand holder):
通过使用内部类,避免在类初始化时创建单例对象,而是将单例对象的创建推迟至第一次请求单例对象时完成,以达到延迟加载的效果。同时单例对象作为内部类的静态属性,这样可以保证单例对象的创建过程是线程安全的
这种实现方式的优势在于使用“延迟加载”的方式解决了实现二中单例对象创建过早浪费系统资源的问题
public class Singleton { private Singleton(){} private static class LazyLoad{ private static final Singleton instance = new Singleton(); } public static Singleton getInstance(){ return LazyLoad.instance; } }
我们可以对单例模式进行一些改进,比如连接池在某种程度上是不是也可以看出是“单例”的?
public class Connection { private static int max_num = 10; private static int num_count = 0; private static Vector<Connection> connPool = new Vector<Connection>(); static{ for( ; num_count < max_num ; num_count++){ Connection conn = new Connection(); System.out.println(num_count+":"+conn.hashCode()); connPool.add(conn); } } private Connection(){} public static Connection getConn() throws Exception{ Random random = new Random(); int num = random.nextInt(max_num); Connection conn = connPool.get(num); System.out.println(conn.hashCode()); return conn; } public static void main(String[] args) throws Exception{ for(int i = 0 ; i<5 ; i++){ Connection.getConn(); } } }
0:3526198 1:7699183 2:14285251 3:10267414 4:27553328 5:4072869 6:1671711 7:11394033 8:4384790 9:9634993 10267414 1671711 1671711 4072869 4384790