前言
单例模式是在编程中常用的一种设计模式,确保某个类只能存在一个对象实例,并供全局调用
单例模式创建
懒汉式
public class HelloService {
private static HelloService instance;
private HelloService() {
}
public static HelloService getInstance() {
if (instance == null) {
instance = new HelloService();
}
return instance;
}
}
懒汉式创建的单例模式线程不安全,在并发下,可能会导致创建了多个实例
保证线程安全的话,加锁就好了
public class HelloService {
private static HelloService instance;
private HelloService() {
}
public static synchronized HelloService getInstance() {
if (instance == null) {
instance = new HelloService();
}
return instance;
}
}
饿汉式
public class HelloService1 {
private static HelloService1 instance = new HelloService1();
private HelloService1() {
}
public static synchronized HelloService1 getInstance() {
return instance;
}
}
饿汉式是线程安全的
静态内部类
public class HelloService2 {
private HelloService2() {
}
public static class Hello {
private static HelloService2 instance = new HelloService2();
}
public static synchronized HelloService2 getInstance() {
return Hello.instance;
}
}
这种也是线程安全的,静态内部类的优点在于,外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE,故而不占内存,只有当调用getInstance()方法才会加载
双重锁模式
public class HelloService3 {
private static HelloService3 instance;
private HelloService3() {
}
public static synchronized HelloService3 getInstance() {
if(instance == null) { //判断是否实例化
synchronized (HelloService3.class) {
if(instance == null) {
instance = new HelloService3();
}
}
}
return instance;
}
}
但这种也是可能造成线程不安全的,需要用到关键字volatile,防止指令重排,是线程安全
public class HelloService3 {
private volatile static HelloService3 instance;
private HelloService3() {
}
public static synchronized HelloService3 getInstance() {
if(instance == null) { //判断是否实例化
synchronized (HelloService3.class) {
if(instance == null) {
instance = new HelloService3();
}
}
}
return instance;
}
}
单例模式注意
单例模式,克隆可破坏、反射可破坏、序列化可破坏等 如克隆
@Data
public class User implements Cloneable {
private Long id;
private String name;
public User clone() throws CloneNotSupportedException {
return (User) super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
User user = new User();
User user1 = user.clone();
System.out.println(user);
System.out.println(user1);
}
}
输出结果为
总结
使用单例模式可以不用频繁的在系统中创建对象,节省了系统资源,使用单例模式可以提高系统性能