文章目录
单例模式(Singleton)-4
懒汉-线程不安全
public class LazySingleton {
private static LazySingleton lazySingleton = null;
private LazySingleton() {
}
/**
* 线程不安全
*/
public static LazySingleton getInstance() {
if (lazySingleton == null) {
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
加锁保证线程安全:在静态方法中直接加锁,并发性能不好。
public static LazySingleton getInstance(){
synchronized (LazySingleton.class){
if(lazySingleton==null){
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
懒汉-线程安全-double check+volatile
提高并发性能
private volatile static LazySingleton lazySingleton = null;
public static LazySingleton getInstance(){
if(lazySingleton==null){
synchronized (LazySingleton.class){
if(lazySingleton==null){
lazySingleton = new LazySingleton();
}
}
}
return lazySingleton;
}
懒汉-线程安全-静态内部类
原理:静态内部类在使用时才加载,不过在加载静态内部类的过程中也会加载外部类,静态内部类有个初始化锁,且初始化只会执行一次,因此线程安全
public class LazyInnerSingleton {
public static class InnerClass{
private static LazyInnerSingleton lazyInnerSingleton = new LazyInnerSingleton();
}
private LazyInnerSingleton() {
}
public static LazyInnerSingleton getInstance(){
return InnerClass.lazyInnerSingleton;
}
}
饿汉-线程安全
立即加载
public class HangrySingleton {
// final修饰后,在类加载的时候就完成赋值,之后不能改变
// private final static HangrySingleton hangrySingleton = new HangrySingleton();
// 静态代码块方式
private final static HangrySingleton hangrySingleton;
static {
hangrySingleton = new HangrySingleton();
}
private HangrySingleton() {
}
public static HangrySingleton getInstance(){
return hangrySingleton;
}
}
原型模式(Prototype )-5
- 用于创建重复的对象,同时又能保证性能。当直接创建对象的代价比较大时,则采用这种模式。
- 实现Cloneable接口,需要重写clone()方法,克隆不调用构造器
使用案例
@Data
public class Pig implements Cloneable{
public Pig(String name, Date birthday) {
this();
this.name = name;
this.birthday = birthday;
}
public Pig() {
System.out.println("对象初始化,步骤多,代价很大...");
}
private String name;
private Date birthday;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
test
@Test
public void test05() throws CloneNotSupportedException {
Date date = new Date(0);
Pig pigInit = new Pig("pig0",date);
for (int i = 0; i < 10; i++) {
Pig pigTemp = (Pig) pigInit.clone();
pigTemp.setName("pig"+i);
pigTemp.setBirthday(new Date());
System.out.println(pigTemp);
}
System.out.println("保存初始值:"+pigInit);
}
打印:
对象初始化,步骤多,代价很大...
Pig(name=pig0, birthday=Thu Jun 04 21:49:39 CST 2020)
...
Pig(name=pig8, birthday=Thu Jun 04 21:49:39 CST 2020)
Pig(name=pig9, birthday=Thu Jun 04 21:49:39 CST 2020)
保存初始值:Pig(name=pig0, birthday=Thu Jan 01 08:00:00 CST 1970)
浅克隆引发的问题
默认浅克隆
浅拷贝引发的问题:
克隆后的对象,虽然对象地址不同,但是其属性是指向同一个引用
@Test
public void test06() throws CloneNotSupportedException {
Date birth = new Date(0L);
Pig pig0 = new Pig("佩奇",birth);
Pig pig1 = (Pig) pig0.clone();
System.out.println(pig0);
System.out.println(pig1);
// 修改引用类型的属性
pig0.getBirthday().setTime(666666666666L);
System.out.println(pig0);
System.out.println(pig1);
}
打印:
对象初始化,步骤多,代价很大...
mxx.design.pattern.creational.prototype.Pig@25f38edcPig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}
mxx.design.pattern.creational.prototype.Pig@3eb07fd3Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}
mxx.design.pattern.creational.prototype.Pig@25f38edcPig{name='佩奇', birthday=Sat Feb 16 09:11:06 CST 1991}
mxx.design.pattern.creational.prototype.Pig@3eb07fd3Pig{name='佩奇', birthday=Sat Feb 16 09:11:06 CST 1991}
pig1的birthday也被修改了。这里需要将该字段变成深克隆
深克隆
在clone方法里对需要深克隆的属性单独克隆
@Override
public Object clone() throws CloneNotSupportedException {
Pig pig = (Pig) super.clone();
pig.birthday = (Date) pig.birthday.clone();
return pig;
}
打印
对象初始化,步骤多,代价很大...
mxx.design.pattern.creational.prototype.Pig@25f38edcPig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}
mxx.design.pattern.creational.prototype.Pig@3eb07fd3Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}
mxx.design.pattern.creational.prototype.Pig@25f38edcPig{name='佩奇', birthday=Sat Feb 16 09:11:06 CST 1991}
mxx.design.pattern.creational.prototype.Pig@3eb07fd3Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}
深克隆后,pig1的birthday没有被修改