单例模式:保证在内存中只有一个实例!
- 饿汉式
类加载到内存后就实例化一个单例,JVM保证线程安全
*简单实用!推荐!
/**单例模式:保证在内存中只有一个实例!
3. 饿汉式
4. 类加载到内存后就实例化一个单例,JVM保证线程安全
*简单实用!推荐!
5. 6. */
public class Mgr01 {
//创建Mgr01的一个对象
private static final Mgr01 INSTANCE = new Mgr01();
//让构造函数成为private,这样类就不会被实例化
private Mgr01() {
}
public static Mgr01 getInstance() {
return INSTANCE;
}
public static void main(String[] args) {
Mgr01 mgr01 = Mgr01.getInstance();
Mgr01 mgr02 = Mgr01.getInstance();
System.out.println(mgr01 == mgr02);
}
}
结果:
true
Process finished with exit code 0
2.懒汉式
- 这种方式解决了在类加载的时候不会直接创建对象,但是这种方式出现了线程安全的问题
public class Mgr02 {
private static Mgr02 INSTANCE = null;
//让构造方法私有
private Mgr02 (){};
//创建方法
public static Mgr02 getInstance(){
try {
Thread.sleep(10); //测试线程安全问题
} catch (InterruptedException e) {
e.printStackTrace();
}
if (INSTANCE == null){
INSTANCE = new Mgr02();
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()-> System.out.println(Mgr02.getInstance().hashCode())).start();
}
}
}
3.懒汉式的进阶版:给方法加 synchronized关键字保证线程安全
- 但是还有进阶版(●’◡’●)
public class Mgr03 {
//
private static Mgr03 INSTANCE = null;
//让构造方法私有
private Mgr03 (){};
//
public synchronized static Mgr03 getInstance(){
if(INSTANCE == null){
INSTANCE = new Mgr03();
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()-> System.out.println(Mgr03.getInstance().hashCode())).start();
}
}
}
4.还可以给代码块加synchronized关键字保证线程安全
public class Mgr04 {
//为什么要加volatile:①线程间可见 ②禁止指令重排序(半初始化过程会出现指令重排序的情况)
private static volatile Mgr04 INSTANCE =null;
private Mgr04 (){};
public static Mgr04 getInstance(){
if (INSTANCE == null){
synchronized (Mgr04.class){
if (INSTANCE == null){
INSTANCE = new Mgr04();
}
}
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()-> System.out.println(Mgr04.getInstance().hashCode())).start();
}
}
}
这种方案采取双重判定,但是代码看上去很复杂。。因此出现了相对优美的方案。
单例模式的最优美的方案之一
5. 采用了静态内部类的方法
- 但是还有最后一种完美的方案!继续往下看ヾ(≧▽≦*)o
public class Mgr05 {
private Mgr05(){};
public static class InstanceHolder{
private static Mgr05 INSTANCE = new Mgr05();
}
public static Mgr05 getInstance(){
return InstanceHolder.INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()-> System.out.println(Mgr05.getInstance().hashCode())).start();
}
}
}
单例模式的最完美的方案出现了
6. 枚举单例!!!不仅安全而且代价量少,优美,最好的方案。
* */
public enum Mgr06 {
INSTANCE;
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()-> System.out.println(Mgr06.INSTANCE.hashCode())).start();
}
}
}