为什么使用单例模式?
我认为是由于某些对象的创建比较耗时,对内存的消耗又比较大回收成本过高,这时候如果允许
不断的创建对象代价势必太高,如果使用单例让内存中始终保持一个对象那么显然更划算反例:
①. 同时执行1000个线程测试
public class Singleton3 { private static Singleton3 INSTANCE; private Singleton3(){} public static Singleton3 getInstance(){ if(INSTANCE == null){ newInstance(); } return INSTANCE; } private static void newInstance(){ INSTANCE = new Singleton3(); } //test public static void main(String[] args) throws InterruptedException, BrokenBarrierException { final CyclicBarrier cb = new CyclicBarrier(1000); for(int i = 0; i <1000;i++){ Thread t = new Thread(new Runnable() { @Override public void run() { try { cb.await(); } catch (Exception e) { e.printStackTrace(); } System.out.println(Singleton3.getInstance().hashCode()); } }); t.start(); } }
测试结果通过notepad++计数发现有几个不一致的发现有不一致的hashcode
11009893 --不一致 31038155 31038155 31038155 31038155 31038155 31038155 31038155 31038155 31038155 31038155 31038155 31038155 26417394 --不一致 31038155 31038155 31038155 ... 省略
②.加锁的方式:
public static Singleton3 getInstance(){ if (INSTANCE == null) { try { // 模拟一个耗时操作 Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized (Singleton3.class) { newInstance(); } } return INSTANCE; } //结果显而易见 18000767 10320474 9913454 2027657 10262576 15487566 15487566 28392674 15487566 6268557 6268557 25920236 ....略
③.双重检查加锁(即做两次判断):这种方式虽然可行,但是使用锁毕竟会加重程序不建议使用
if (INSTANCE == null) { try { // 模拟一个耗时操作 Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized (Singleton3.class) { newInstance(); } } return INSTANCE; } private static void newInstance(){ if(INSTANCE == null){ INSTANCE = new Singleton3(); } }
------------------------------------------
使用如下几种方式:
①.静态块的方式:只会第一次创建对象的方式进来
private static final Singleton2 INSTANCE; static{ System.out.println("static."); INSTANCE = new Singleton2(); } private Singleton2(){} public static Singleton2 getInstance(){ return INSTANCE; }
②.类似于①
private static final Singleton INSTANCE = new Singleton(); private Singleton(){ System.out.println("construct."); } public static Singleton getInstance(){ return INSTANCE; }
③.枚举的方式(必须是单元素):
public enum Singleton4 { INSTANCE; public int get(){ try { // 模拟耗时 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return Singleton4.class.hashCode(); } }
④.静态内部类:略
------------------------------------