1、饿汉式:
/**
* 单例:饿汉式
* 缺点:可能会浪费空间
*/
public class Singleton_Hurry {
private static final Singleton_Hurry HURRY = new Singleton_Hurry();
//构造器私有化
private Singleton_Hurry() {
System.out.println("成功创建对象!"+System.currentTimeMillis());
}
/**
* 提供公有方法来获取实例
* @return
*/
public static Singleton_Hurry getInstance() {
return HURRY;
}
public static void main(String[] args) {
Singleton_Hurry h1 = Singleton_Hurry.getInstance();
Singleton_Hurry h2 = Singleton_Hurry.getInstance();
System.out.println(h1.hashCode()); //1265094477
System.out.println(h2.hashCode()); //1265094477
}
}
2、懒汉式:
/**
* 单例:懒汉
* 这种写法在单线程上是可以,但在多线程下会出现并发问题
*/
public class Singleton_Lazy {
//构造器私有化
private Singleton_Lazy() {
System.out.println(Thread.currentThread().getName()+"ok!");
}
private static Singleton_Lazy LAZY;
public static Singleton_Lazy getInstance() {
if (LAZY == null) {
LAZY = new Singleton_Lazy();
}
return LAZY;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
Singleton_Lazy.getInstance();
}).start();
}
}
}
支持多线程的懒汉式:
/**
* 单例:懒汉
* 支持多线程(双重检测锁)
* 问题:不加 volatile会造成指令成排(可能创建不了实例)
*/
public class Singleton_Lazy {
// 构造器私有化
private Singleton_Lazy() {
System.out.println(Thread.currentThread().getName() + "ok!");
}
// 避免指令重排
private volatile static Singleton_Lazy lazy;
public static Singleton_Lazy getInstance() {
// 双重检测锁模式的单例 (DCL)
if (lazy == null) {
synchronized (Singleton_Lazy.class) {
if (lazy == null) {
lazy = new Singleton_Lazy();//它不是原子性操作
//1.分配内存空间 2.执行构造方法,初始化对象 3.把这个对象指向这个空间
}
}
}
return lazy;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
Singleton_Lazy.getInstance();
}).start();
}
}
}
3、静态内部类
public class Holder {
public static Holder getInstance(){
return InnerClass.HOLDER;
}
public static class InnerClass {
private static final Holder HOLDER = new Holder();
}
}
前三种单例会被反射破解:
public class Singleton_Lazy {
// 构造器私有化
private Singleton_Lazy() {
System.out.println(Thread.currentThread().getName() + "ok!");
}
// 避免指令重排
private volatile static Singleton_Lazy lazy;
public static Singleton_Lazy getInstance() {
// 双重检测锁模式的单例 (DCL)
if (lazy == null) {
synchronized (Singleton_Lazy.class) {
if (lazy == null) {
lazy = new Singleton_Lazy();//它不是原子性操作
//1.分配内存空间 2.执行构造方法,初始化对象 3.把这个对象指向这个空间
}
}
}
return lazy;
}
public static void main(String[] args) throws Exception {
Singleton_Lazy lazy1 = Singleton_Lazy.getInstance();
System.out.println(lazy1.hashCode());
// 使用反射来破坏单例
Constructor<Singleton_Lazy> constructor = Singleton_Lazy.class.getDeclaredConstructor(null);
constructor.setAccessible(true);//可以访问私有的构造器
Singleton_Lazy lazy2 = constructor.newInstance();
System.out.println(lazy2.hashCode());
}
}
解决单例被破解:
/**
* 三重检测锁
*/
public class Singleton_Lazy {
// 构造器私有化
private Singleton_Lazy(){
synchronized (Singleton_Lazy.class) {
if (lazy != null) {
throw new RuntimeException("不要试图使用反射破坏异常!");
}
}
}
// 避免指令重排
private volatile static Singleton_Lazy lazy;
public static Singleton_Lazy getInstance() {
// 双重检测锁模式的单例 (DCL)
if (lazy == null) {
synchronized (Singleton_Lazy.class) {
if (lazy == null) {
lazy = new Singleton_Lazy();//它不是原子性操作
//1.分配内存空间 2.执行构造方法,初始化对象 3.把这个对象指向这个空间
}
}
}
return lazy;
}
public static void main(String[] args) throws Exception {
Singleton_Lazy lazy1 = Singleton_Lazy.getInstance();
System.out.println(lazy1.hashCode());
// 使用反射来破坏单例
Constructor<Singleton_Lazy> constructor = Singleton_Lazy.class.getDeclaredConstructor(null);
constructor.setAccessible(true);//可以访问私有的构造器
Singleton_Lazy lazy2 = constructor.newInstance();
System.out.println(lazy2.hashCode());
}
}
此时创建对象也不是单例:
public class Singleton_Lazy {
// 构造器私有化
private Singleton_Lazy(){
synchronized (Singleton_Lazy.class) {
if (lazy != null) {
throw new RuntimeException("不要试图使用反射破坏异常!");
}
}
}
// 避免指令重排
private volatile static Singleton_Lazy lazy;
public static Singleton_Lazy getInstance() {
// 双重检测锁模式的单例 (DCL)
if (lazy == null) {
synchronized (Singleton_Lazy.class) {
if (lazy == null) {
lazy = new Singleton_Lazy();//它不是原子性操作
//1.分配内存空间 2.执行构造方法,初始化对象 3.把这个对象指向这个空间
}
}
}
return lazy;
}
public static void main(String[] args) throws Exception {
// Singleton_Lazy lazy1 = Singleton_Lazy.getInstance();
// System.out.println(lazy1.hashCode());
// 使用反射来破坏单例
Constructor<Singleton_Lazy> constructor = Singleton_Lazy.class.getDeclaredConstructor(null);
constructor.setAccessible(true);//可以访问私有的构造器
Singleton_Lazy lazy2 = constructor.newInstance();
System.out.println(lazy2.hashCode());
Singleton_Lazy lazy3 = constructor.newInstance();
System.out.println(lazy3.hashCode());
}
}
解决方法:
public class Singleton_Lazy {
//红绿灯
private static boolean baidou = false;
// 构造器私有化
private Singleton_Lazy() {
synchronized (Singleton_Lazy.class) {
if (baidou == false) {
baidou = true;
} else {
throw new RuntimeException("不要试图使用反射破坏异常!");
}
}
}
// 避免指令重排
private volatile static Singleton_Lazy lazy;
public static Singleton_Lazy getInstance() {
// 双重检测锁模式的单例 (DCL)
if (lazy == null) {
synchronized (Singleton_Lazy.class) {
if (lazy == null) {
lazy = new Singleton_Lazy();//它不是原子性操作
//1.分配内存空间 2.执行构造方法,初始化对象 3.把这个对象指向这个空间
}
}
}
return lazy;
}
public static void main(String[] args) throws Exception {
Singleton_Lazy lazy1 = Singleton_Lazy.getInstance();
System.out.println(lazy1.hashCode());
// 使用反射来破坏单例
/*Constructor<Singleton_Lazy> constructor = Singleton_Lazy.class.getDeclaredConstructor(null);
constructor.setAccessible(true);//可以访问私有的构造器
Singleton_Lazy lazy2 = constructor.newInstance();
System.out.println(lazy2.hashCode());*/
Singleton_Lazy lazy3 = Singleton_Lazy.getInstance();
System.out.println(lazy3.hashCode());
}
}
但还是能被反射破解