设计模式之单例模式深究

为什么使用单例模式?
        我认为是由于某些对象的创建比较耗时,对内存的消耗又比较大回收成本过高,这时候如果允许
不断的创建对象代价势必太高,如果使用单例让内存中始终保持一个对象那么显然更划算

反例:

    ①. 同时执行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();
	}
}

④.静态内部类:略

------------------------------------

 

转载于:https://my.oschina.net/u/2486137/blog/1589610

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值