理论写着写着就明白了
应用场景
- 只需要一个实例
- 实际工作中个人应用比较多的地方都是一些工具类如Redis Property 等
二话不说先上代码 单例写法及小测试
//饿汉
//类加载到内存后,就实例化一个单例,JVM保证线程安全
public class Mrg01 {
private static final Mrg01 INSTANCE = new Mrg01();
private Mrg01(){}
public static Mrg01 getInstance(){return INSTANCE;}
public static void main(String[] args) {
Mrg01 mrg01 = Mrg01.getInstance();
Mrg01 mrg02 = Mrg01.getInstance();
System.out.println(mrg01 == mrg02);
}
}
我个人时比较喜欢这种写法,简单,便捷。
网上关于单例的写发有很多,其实实际工作中能解决问题就好。
补充几种别的写法确实很巧妙啊---->
/**
* 懒汉
*
* 虽然达到按需初始化,但会造成多线程不同实例问题
* 可以用syn锁及双重判断来解决实例化问题 这里就不写了
*/
public class Mrg02 {
private static Mrg02 INSTANCE;
public Mrg02() {
}
public static Mrg02 getInstance(){
if(INSTANCE == null){
/*try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
INSTANCE = new Mrg02();
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(() -> {
System.out.println(Mrg02.getInstance().hashCode());
}).start();
}
}
/**
* 静态内部类
* JVM保证单例
* 加载外部类时不会加载内部类 这样实现懒加载
*/
public class Mgr03 {
public Mgr03() {
}
private static class Mgr03Holder{
private final static Mgr03 INSTANCE = new Mgr03();
}
public static Mgr03 getInstance(){
return Mgr03Holder.INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(Mgr03.getInstance().hashCode());
}
}
}
/**
* 不仅可以解决线程同步,还可以防止反序列化
* Effevtive Java 中的一种关于单例的写发
*/
public enum Mgr04 {
INSTANCE;
Mgr04{
//具体的业务逻辑 枚举构造这个只会被调用一次 实现懒加载
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(() -> {
System.out.println(Mgr04.INSTANCE.hashCode());
}).start();
}
}
}