创建单例类有以下几种方式:
饿汉式
懒汉式(加同步锁的懒汉式、加双重校验锁的懒汉式、防止指令重排优化的懒汉式)
登记式单例模式
静态内部类单例模式
枚举类型的单例模式
备注:
其中“枚举类型的单例模式。”最牛逼,可以防止反射调用构造器
饿汉式;
public class MyManger {
private static MyManger instance=new MyManger();
private MyManger() {
}
public static MyManger getInstance() {
return instance;
}
}
懒汉式-加同步锁的懒汉式
public class MyManger2 {
private static MyManger2 instance;
private MyManger2() {
}
public static synchronized MyManger2 getInstance() {
if(instance==null){
instance=new MyManger2();
}
return instance;
}
}
懒汉式-加双重校验锁的懒汉式
public class MyManger3 {
private static MyManger3 instance;
private MyManger3() {
}
public static MyManger3 getInstance() {
if(instance==null){
synchronized (MyManger3.class){
if(instance==null){
instance=new MyManger3();
}
}
}
return instance;
}
}
懒汉式-加双重校验锁&防止指令重排序的懒汉式
public class MyManger3 {
private static volatile MyManger3 instance;
private MyManger3() {
}
public static MyManger3 getInstance() {
if(instance==null){
synchronized (MyManger3.class){
if(instance==null){
instance=new MyManger3();
}
}
}
return instance;
}
}
登记式单例模式;
就是将该类名进行登记,每次调用前查询,如果存在,则直接使用;不存在,则进行登记。
public class MyManger4 {
private static volatile MyManger4 instance;
private static Map
private MyManger4() {
}
public static MyManger4 getInstance(String name) {
if (null == name) {
name = MyManger4.class.getName();
System.out.println("name == null --- > name == " + name);
}
if (null == map.get(name)) {
try {
map.put(name, (MyManger4) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return map.get(name);
}
}
静态内部类单例模式;
public class MyManger5 {
private static volatile MyManger5 instance;
private MyManger5() {
}
private static class SingletonHolder {
private static MyManger5 instance = new MyManger5();
}
public static MyManger5 getInstance( ) {
return SingletonHolder.instance;
}
}
枚举类型的单例模式
在枚举中我们明确了构造方法限制为私有,在我们访问枚举实例时会执行构造方法,同时每个枚举实例都是static final类型的,也就表明只能被实例化一次。在调用构造方法时,我们的单例被实例化。也就是说,因为enum中的实例被保证只会被实例化一次,所以我们的INSTANCE也就会被实例化一次。
public enum MyManger6 {
INSTANCE;
private MyResource instance;
MyManger6() {
instance = new MyResource();
}
public MyResource getInstance() {
return instance;
}
}
class MyResource {
public void doMethod() {
System.out.println("枚举类型的单例类资源");
}
}
// getInstance 示例
MyResource myResource=MyManger6.INSTANCE.getInstance();
[Singleton单例模式的几种创建方法](https://blog.csdn.net/hl_java/article/details/70148622)
[Singleton单例模式-如何防止JAVA反射对单例类的攻击?](https://blog.csdn.net/hl_java/article/details/71511839)
[Singleton单例模式-如何防止序列化对单例类的攻击?](https://blog.csdn.net/hl_java/article/details/87464951)
[Singleton单例模式-【懒汉式-加双重校验锁&防止指令重排序的懒汉式】实现方案中为什么需要加volatile关键字?](https://blog.csdn.net/hl_java/article/details/89160086)