使用客户端加锁的Vector的复合操作
在我的上一盘博文中,
public class SafeContainer { |
在这段代码中,我并不想把我的vector直接暴露给我外界,我只想允许其它类调用这个类二次封装的操作vector的方法来修改vector里面的属性。并且其它所有的类访问的都得是同一个vector里的内容。最简单的方式就是让这个类只能有一个对象。这个时候需要考虑的就是单例模式的设计。
单例模式的特点
单例模式只能有一个实例。
单例类必须创建自己的唯一实例。
单例类必须向其他对象提供这一实例。
单例模式与静态类对比
静态类据我所知用的比较多的地方就是在建造者模式中,这篇文章中写的对比很详细。建议参考该文章。
单例模式的实现
懒汉模式(Lazy loading)
一开始的代码里使用的就是懒汉模式,在这个类创建的时候,并没有创建单例绑定到类的static域上,这个办法使用了非常明显的lazy load。所以叫懒汉模式,但是上面的代码不是线程安全的,所以需要处理同步。饿汉模式
private Vector<Integer> vector;
private static SafeContainer safeContainer = new SafeContainer();
private SafeContainer() {
vector = new Vector<>();
}
public static SafeContainer getSafeContainer() {
for (int i = 0; i < 50; i++) {
safeContainer.addLast(i);
}
return safeContainer;
}
这里就相当于是直接把单例绑定到了safeContainer上了
- 静态类内部加载
private Vector<Integer> vector;
private static class SingletonHelper {
private static SafeContainerStaticLoad safeContainerStaticLoad= new SafeContainerStaticLoad();
}
public static SafeContainerStaticLoad getInstance() {
return SingletonHelper.safeContainerStaticLoad;
}
private SafeContainerStaticLoad() {
vector = new Vector<>();
}
就是使用静态类内部的static字段来实现加载对象,使用内部类的好处是,静态内部类不会在单例加载时就加载,而是在调用getInstance()方法时才进行加载,达到了类似懒汉模式的效果,而这种方法又是线程安全的。
- 枚举方法
这个算是最好用,也是最简单的单例模式实现了SAFE_CONTAIN_ENUM();
private Vector<Integer> vector;
SafeContainEnum() {
vector = new Vector<>();
}
莫得了。它实现了
自由序列化。
保证只有一个实例。
线程安全。
- 双重校验锁法
public class SingletonDemo {
private static volatile SingletonDemo instance;
private SingletonDemo(){
System.out.println("Singleton has loaded");
}
public static SingletonDemo getInstance(){
if(instance==null){
synchronized (SingletonDemo.class){
if(instance==null){
instance=new SingletonDemo();
}
}
}
return instance;
}
}
丢一段代码吧,这个挺好理解的,这个其实就是两个线程调用getInstance方法的时候,由于对SingletonDemo.class加锁了,然后在一个线程获得实例的时候,另一个线程由于可见性,知道了instance对象不为空,所以就得到了第一个线程返回的对象的引用。