单例模式的特点:
单例模式的分类:
用处:
一般用在配置文件的读取,有些东西只需要加载一次,以后重复使用。
示例代码:
package myThread; /** * 单例模式,懒汉模式 * * @author Champion.Wong * */ public class LazySingleton { private static LazySingleton singleton = null; /** * 私有的构造方法,防止被多次实例化 * */ private LazySingleton() { } /** * 静态工厂,返回此类的唯一一个实例 判断,如果没有被实例化,则先初始化再返回 * * @return LazySingleton */ public static LazySingleton getInstance() { if (null == singleton) singleton = new LazySingleton(); return singleton; } }
package myThread; /** * 单例模式,饿汉模式 * @author Champion.Wong * */ public class EagerSingleton { private static EagerSingleton singleton = new EagerSingleton(); // 强制初始化,在类加载的时候就创建好了对象 /** * 私有的构造方法,防止被多次实例化 * */ private EagerSingleton() { } public static EagerSingleton getInstance() { return singleton; } }
所以,在EagerSingleton中加入属性:createdTime
package myThread; /** * 单例模式,饿汉模式 * @author Champion.Wong * */ public class EagerSingleton { private static EagerSingleton singleton = new EagerSingleton(); // 强制初始化,在类加载的时候就创建好了对象 /** * 私有的构造方法,防止被多次实例化 * */ private EagerSingleton() { createdTime = System.currentTimeMillis(); } public static EagerSingleton getInstance() { return singleton; } private long createdTime = 0L; //此类的创建时间,在类实例化的时候赋值 public long getCreatedTime() { return createdTime; } }
package myThread; public class Test_Singleton { public static void main(String[] args) { EagerSingleton singleton1 = EagerSingleton.getInstance(); try { Thread.sleep(2000); //让当前线程睡眠2000ms,这样,两个对象实例化的时间就差2s } catch (InterruptedException e) { e.printStackTrace(); } EagerSingleton singleton2 = EagerSingleton.getInstance(); System.out.println("Singleton1:" + singleton1.getCreatedTime()); System.out.println("Singleton2:" + singleton2.getCreatedTime()); } }
两个对象的实例化的时间相同,证明单例设想成功!
当多个线程访问单例类的时候,必须要保证同时只能由一个线程访问,当这个线程访问结束了,其它线程才能访问。这是就要给单例的访问方法加个同步锁(synchronized)。
修改后的LazySingleton为:
package myThread; /** * 单例模式,懒汉模式 * * @author Champion.Wong * */ public class LazySingleton { private static LazySingleton singleton = null; /** * 私有的构造方法,防止被多次实例化 * */ private LazySingleton() { } /** * 静态工厂,返回此类的唯一一个实例 判断,如果没有被实例化,则先初始化再返回 * * @return LazySingleton */ synchronized public static LazySingleton getInstance() { if (null == singleton) singleton = new LazySingleton(); System.out.println(Thread.currentThread().getName() + System.currentTimeMillis()); try { Thread.sleep(900); //假设每个线程访问的时候都需要耗费一定的时间 } catch (InterruptedException e) { e.printStackTrace(); } return singleton; } }
package myThread; public class Test_Thread_Singleton { /** * @param args */ public static void main(String[] args) { SingletonThread st = new SingletonThread(); SingletonThread st1 = new SingletonThread(); st.start(); st1.start(); } } class SingletonThread extends Thread { private LazySingleton singleton = null; public void run() { while (!this.isInterrupted()) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } singleton = LazySingleton.getInstance(); } } }
时间差不多都不一致,同步成功!限制了同时访问。