单例模式
JAVA类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
特点
- 单例模式类,只能有一个实例
- 单例类必须自己创建自己的唯一实例
- 单例类必须给所有其他对象提供这一实例
优点
- 确保所有对象都访问一个实例,确保了访问唯一性
- 具有伸缩性,类自己控制实例化进程,类就在改变实例化进程上有响应的伸缩性
- 节约资源,在系统内存中只存在一个对象,可以节约系统资源,避免重复资源消耗等问题
缺点
- 对于不同用例场景变化的对象,可能会引起数据错误,不能保存彼此的状态
- 没有抽象层,扩展难度大
- 职责过重,违反“单一指责原则”
- 可能造成连接池溢出,或者内存对象丢失
饿汉单例模式(预先加载法)
public class test1 {
private test1() {
}
public int value;
public static test1 instance = new test1();
public test1 getInstance() {
return instance;
}
public void setInt(int i){
value=i;
}
public Integer getInt(){
return value;
}
}
class domian{
public static void main(String[] args) {
test1 t1=test1.instance.getInstance();
t1.setInt(10);
System.out.println(t1.getInt());
test1 t2=test1.instance.getInstance();
System.out.println(t2.getInt());
}
}
/** 结果
10
10
**/
优点:
- 1.线程安全
- 2.在类加载的同事已经创建好一个静态对象,调用反应快
缺点:
- 资源效率低,可能getInstance()永远不会执行到,但执行该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化
懒汉单例模式
class test1 {
public static test1 instance = null;
public Integer value;
private test1() {
}
public static test1 getInstance() {
if (instance == null) {
//多个线程判断instance都为null时,在执行new操作时多线程会出现重复情况
instance = new test1();
}
return instance;
}
public void setInt(int i) {
value = i;
}
public int getInt() {
return value;
}
}
class domain {
public static void main(String[] args) {
test1 t1 = test1.getInstance();
t1.setInt(10);
System.out.println(t1.getInt());
test1 t2 = test1.getInstance();
System.out.println(t2.getInt());
}
}
/** 结果
10
10
**/
优点:
- 1.资源利用率高,不执行getInstance()就不会被实例,可以执行该类的其他静态方法。
缺点:
- 线程不安全,没有加synchronized,多线程容易创建多个实例
双验锁/双重校验锁(DCL,double-checked locking双重检查锁定)
public class test1 {
//volatile让变量每次在使用的时候,都从主存中取。而不是从各个线程的“工作内存”。
private volatile static test1 singleton;
public Integer value;
private test1 (){}
public static test1 getSingleton() {
if (singleton == null) {
//synchronized 同步锁
synchronized (test1.class) {
if (singleton == null) {
singleton = new test1();
}
}
}
return singleton;
}
public void serInt(int i){
value=i;
}
public int getInt(){
return value;
}
}
class domain{
public static void main(String[] args) {
test1 t1=test1.getSingleton();
t1.serInt(10);
System.out.println(t1.getInt());
test1 t2=test1.getSingleton();
System.out.println(t2.getInt());
t2.serInt(20);
System.out.println(t1.getInt());
}
}
/** 结果
10
10
20
**/
优点:
- 1.线程安全,
缺点:
- 双验锁机制,每次都要进行lock,造成额外的性能开销。
登记式-静态内部类
public class test1 {
public Integer value;
private static class SingletonHolder {
private static final test1 INSTANCE = new test1();
}
private test1() {
}
public static final test1 getSingleton() {
return SingletonHolder.INSTANCE;
}
public void serInt(int i) {
value = i;
}
public int getInt() {
return value;
}
}
class domain {
public static void main(String[] args) {
test1 t1 = test1.getSingleton();
t1.serInt(10);
System.out.println(t1.getInt());
test1 t2 = test1.getSingleton();
System.out.println(t2.getInt());
t2.serInt(20);
System.out.println(t1.getInt());
}
}
/** 结果
10
10
20
**/
优点:
- 1.线程安全,