单例类需要满足以下几个点
- 1.单例类只能有一个实例
- 2.实例只能自己生成
- 3.像其他所有对象提供这一实例
单例模式的应用
- 多线程情况下保证资源的一致性,例如多台打印机打印一个文件。
### 单例模式的写法
饿汉式
>线程安全
```java
public class EagerSingleton
{
private static EagerSingleton instance = new EagerSingleton();
private EagerSingleton()
{
}
public static EagerSingleton getInstance()
{
return instance;
}
}
```
饿汉式就是在调用getInstance这个方法的时候实例直接被创建,并不进行判断实例是否为空。由于实例是被直接创建,所以并不可以延迟加载(Lazy Loading),容易产生垃圾对象。
还有一个问题,饿汉式是如何保证线程安全的?
>假如线程1实例化一个EagerSingleton的同时线程2也在实例化,那么对象不就产生两个内存地址了嘛?事实上是java虚拟机帮我们解决了这个问题。
JVM的解决办法
>当jvm遇到new这个关键字的时候,首先会检查符号引用是否已经存在常量池中,(这句话的意思就是新创建的对象是否已经存在),如果没有的话就开始为新建的对象分配内存。
>分配内存有两种方式:假如内存规整,就用第一种指针碰撞(Bump the Pointer),就是向空闲的内存区挪动一段位移。假如内存不规整,就采用空闲列表(Free List),从列表上选取一段足够大的内存。
>对象创建是很频繁的行为,如果线程1给A分配内存的时候,线程2也在给B分配内存,无论采取何种方式分配内存,都有可能将B的内存分配给A。
>解决问题的两种方案:一种是对分配动作同步处理,采用[CAS](https://blog.csdn.net/liubenlong007/article/details/53761730)配上失败重试的方式保证更新操作的原子性。另一种将先对线程分配空间,在他们自己的空间里进行操作,称之为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB),分配空间用完时,才需要同步锁定。
懒汉式
>顾名思义,是可以Lazy Loading的,但是线程不安全
```java
public class LazySingleton
{
private static volatile LazySingleton instance = null;
private LazySingleton()
{
}
public static LazySingleton getInstance()
{
if (instance == null)
instance = new LazySingleton();
return instance;
}
}
```
双检索
>线程安全,Lazy Loading
```java
public class DoubleCheckLockSingleton
{
private static DoubleCheckLockSingleton instance = null;
private DoubleCheckLockSingleton()
{
}
public static DoubleCheckLockSingleton getInstance()
{
if (instance == null)
{
synchronized (DoubleCheckLockSingleton.class)
{
if (instance == null)
instance = new DoubleCheckLockSingleton();
}
}
return instance;
}
}
```
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有