前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式之单例模式深究

设计模式之单例模式深究

作者头像
用户1215919
发布2018-02-27 10:37:14
5000
发布2018-02-27 10:37:14
举报

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

反例:

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

④.静态内部类:略

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档