判断是否存在
/** * 懒汉式 */ public class LazySingleInstance { // 私有构造方法 private LazySingleInstance(){}; // 私有的类对象 private static LazySingleInstance instance = null; // 缺点: // 1 每次都需要去判断instance 是否为空 // 2 调用时才去new对象,响应比较慢 // 3 多线程时,线程不安全,多线程同时获取该对象,线程不安全,可能会产生多个对象出来 public static LazySingleInstance getInstance() throws InterruptedException { // 每次都需要判断instance是否为空,浪费资源 if (null == instance) { Thread.sleep(1000); instance = new LazySingleInstance(); } return instance; } }
考虑线程
/** * 懒汉式线程安全方法一 */ public class ThreadSafeSingleInstance { // 私有的静态实例 private static ThreadSafeSingleInstance instance; // 私有的构造方法 private ThreadSafeSingleInstance(){}; /** * 懒汉式线程安全方法 * 同步锁保护 * 缺点: * 性能低下,且同时每次均需检查实例是否存在 * @return * @throws InterruptedException */ public synchronized static ThreadSafeSingleInstance getInstance() throws InterruptedException { if (instance == null) { Thread.sleep(1000); instance = new ThreadSafeSingleInstance(); } return instance; } }
/** * 懒汉式线程安全方法二 */ public class ThreadSafeSingleInstance { // 私有的静态实例 private static ThreadSafeSingleInstance instance; // 私有的构造方法 private ThreadSafeSingleInstance(){}; /** * 同步块保护加二次判断 * 解决问题 */ public static ThreadSafeSingleInstance getInstance() throws InterruptedException { if (instance == null) { // 进方法后进行实例判断,若实例为空,进入同步块 // 多线程时,多个线程会同时进入到同步块外面等待 // 此时,一个线程拿到ThreadSafeSingleInstance.class 后,其他线程在synchronized块外面等待 // 待锁释放时,一个等待的线程拿到锁,同时再次检查实例是否为空 // 并决定是否要创建实例 synchronized (String.class) {//ThreadSafeSingleInstance.class) { Thread.sleep(1000); if (instance == null) { instance = new ThreadSafeSingleInstance(); } } } return instance; } }
每次都去new
/** * 饿汉式 */ public class HungrySingleInstance { // 私有的构造方法 private HungrySingleInstance(){}; // 静态类变量,初始化类时变创建对象 private static HungrySingleInstance instance = new HungrySingleInstance(); // 或采用静态块形式初始化instance static { instance = new HungrySingleInstance(); } /** * 获取实例方法 * 优点: * 线程安全,且不存在懒汉式的二次判断问题 * 缺点: * 初始化即new 实例对象出来,违背资源利用习惯(即不管用不用都初始化实例出来) * @return */ public static HungrySingleInstance getInstance() { return instance; } }
测试类
public class SingleInstanceTest implements Runnable{ HungrySingleInstance hungrySingleInstance = null; LazySingleInstance lazySingleInstance = null; ThreadSafeSingleInstance threadSafeSingleInstance = null; // @Override // public void run() { // hungrySingleInstance = HungrySingleInstance.getInstance(); // System.out.println("hungrySingleInstance.hashCode() " + hungrySingleInstance.hashCode()); // // } // @Override // public void run() { // try { // lazySingleInstance = LazySingleInstance.getInstance(); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println("lazySingleInstance.hashCode() " + lazySingleInstance.hashCode()); // } @Override public void run() { try { threadSafeSingleInstance = ThreadSafeSingleInstance.getInstance(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("threadSafeSingleInstance() " + threadSafeSingleInstance.hashCode()); } public static void main(String args[]) throws InterruptedException{ SingleInstanceTest singleInstanceTest = new SingleInstanceTest(); for (int i=0; i< 100; i++) { Thread t = new Thread(singleInstanceTest, String.valueOf(i)); t.start(); } } }