Design pattern ——singleton pattern(单例总结深思)

Talk is cheap  Show me the code

个人学习笔记--仅供参考

单例模式可以保证内存里只有一个实例,减少了内存开销;可以避免对资源的多重占用。
单例模式看起来非常简单,实现起来其实也非常简单。

总结一下,

前几章主要讲了

饿汉式:

1,经典饿汉式 2静态代码块饿汉式

优点:没有加任何的锁、执行效率比较高,在用户体验上来说,比懒汉式更好。
缺点:类加载的时候就初始化,不管用与不用都占着空间,浪费了内存,有可能占着茅

懒汉式

1,普通懒汉式 :线程不安全

2,  两种加锁懒汉式,互斥锁解决线程安全,synchronized,容易阻塞

3. 双重检查锁,即利用volatile 和 synchronized 关键字,保证可见性和原子性,降低阻塞

其他式

1,,静态内部类方式  ,去除了锁,线程也是安全的

2.枚举式   JDK 底层 ,只有一个protected构造方法 ,枚举式单例也是《Effective
Java》书中推荐的一种单例实现写法。在JDK 枚举的语法特殊性,以及反射也为枚举保
驾护航,让枚举式单例成为一种比较优雅的实现。

3.注册式  非线程安全

这些看起开都解决了单例,时间上,通过java 反射机制,序列化和反序列化,都可以破坏。

所以解决方案:

1.不要实现Serializable接口,如果有Serializable ,可以利用构造一个自己的readResolve() 屏蔽新生成的对象

彩蛋:Serializable,生成新对象是从内存中直接拷贝的,不会调用new方法,也叫深度拷贝,

2.反射只需要再构造方法中,判断返回的实例是不是空的,只允许非空下返回

再由此发散

研究下ThreadLocal
ThreadLocal 不能保证其
创建的对象是全局唯一,但是能保证在单个线程中是唯一的,天生的线程安全

package pattern;

public class ThreadLocalSingleton {
	private ThreadLocalSingleton() {}
	private static final ThreadLocal<ThreadLocalSingleton>  
	     tl= new ThreadLocal<ThreadLocalSingleton>() {
		@Override
		protected ThreadLocalSingleton initialValue() {
			return new ThreadLocalSingleton();
		}
	};
	public static ThreadLocalSingleton getInstance() {
		return tl.get();
		
	}
	public static void main(String[] args) {
		System.out.println(ThreadLocalSingleton.getInstance());
		System.out.println(ThreadLocalSingleton.getInstance());
		System.out.println(ThreadLocalSingleton.getInstance());
		System.out.println(ThreadLocalSingleton.getInstance());
		System.out.println(ThreadLocalSingleton.getInstance());
		Thread t1 = new Thread(new Runnable() {

			@Override
			public void run() {
				ThreadLocalSingleton h1 = ThreadLocalSingleton.getInstance();
				System.out.println(Thread.currentThread().getName() + ":" + h1);

			}
		});
		Thread t2 = new Thread(new Runnable() {

			@Override
			public void run() {
				ThreadLocalSingleton h2 = ThreadLocalSingleton.getInstance();
				System.out.println(Thread.currentThread().getName() + ":" + h2);

			}
		});
		t1.start();
		t2.start();
		

		System.out.println("End");
	}
  }

结果

pattern.ThreadLocalSingleton@7852e922
pattern.ThreadLocalSingleton@7852e922
pattern.ThreadLocalSingleton@7852e922
pattern.ThreadLocalSingleton@7852e922
pattern.ThreadLocalSingleton@7852e922
End
Thread-1:pattern.ThreadLocalSingleton@28d0be7
Thread-0:pattern.ThreadLocalSingleton@17135162

我们发现,在主线程main 中无论调用多少次,获取到的实例都是同一个,都在两个子线
程中分别获取到了不同的实例。那么ThreadLocal 是如果实现这样的效果的呢?我们知
道上面的单例模式为了达到线程安全的目的,给方法上锁,以时间换空间。ThreadLocal
将所有的对象全部放在ThreadLocalMap 中,为每个线程都提供一个对象,实际上是以
空间换时间来实现线程间隔离的。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值