设计模式之单例模式深究

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

反例:

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

④.静态内部类:略

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一个爱吃西瓜的程序员

学习SQL【7】-函数

终于可以开原创标识和留言功能了,开心。我坚信努力总会有收获的。 不仅SQL, 对所有的编程语言来说,函数都起着至关重要的作用。函数就像是编程语言的“道具箱”...

35712
来自专栏GreenLeaves

SQL练习之求解填字游戏

SELECT * FROM dbo.spt_values ? 假设我们需要找具有以下特点的单词: (1)第二个字母:a (2)第四个字母:l (3)一共只有5个...

19510
来自专栏Python爬虫实战

MySQL从零开始:05 MySQL数据类型

距离上次更新 MySQL 从零开始系列,已经过去了十几天,时间隔得有点长,由于我选用的是 MySQL 的最新版本,网上的教程大多停留在 MySQL 5.x,所以...

1523
来自专栏乐沙弥的世界

PL/SQL 联合数组与嵌套表

      通常情况下,在PL/SQL中,处理单行单列的数据可以使用标量变量,而处理单行多列的数据则使用PL/SQL记录是不错的选择。单列多行数据 则由联合数组...

1143
来自专栏Ken的杂谈

SQL开发中的良好习惯

1231
来自专栏祥子的故事

sql | 基础总结 | 思维导图

3976
来自专栏Java后端生活

MySQL(三)基础查询

1519
来自专栏前端儿

一种排序

现在有很多长方形,每一个长方形都有一个编号,这个编号可以重复;还知道这个长方形的宽和长,编号、长、宽都是整数;现在要求按照一下方式排序(默认排序规则都是从小到大...

1012
来自专栏抠抠空间

MySQL之表的数据类型

一 介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 详细参考: http://www.runoob....

3678
来自专栏数据和云

深入剖析:认识Oracle 中的 NULL 值

杨廷琨,网名 yangtingkun 云和恩墨技术总监,Oracle ACE Director,ACOUG 核心专家 经常看到很多人提出和NULL有关的问题。N...

3035

扫码关注云+社区

领取腾讯云代金券