单例设计模式
功能:保证某个类在系统中只有一个对象
枚举实现- 注解
public enum Boss {
boss;
}
- 测试代码:
public static void main(String[] args) throws IOException {
Boss boss1 = Boss.boss;
Boss boss2 = Boss.boss;
System.out.println(boss1 == boss2);
}
内部类
原理:静态内部类不会随着外部类的加载和初始化而初始化,它是要单独加载和初始化的。 因为是在内部类加载和初始化时对象才初始化时,是线程安全的。
public class Boss {
private Boss() {
}
//在内部类被加载和初始化时,才会创建Boss的实体对象
private static class InnerClass {
private static Boss boss = new Boss();
}
public static Boss getBossInstance() {
return InnerClass.boss;
}
}
饿汉式
- 构造方法私有化
- 提供一个静态的当前类的实例并实例化
- 提供一个静态方法返回2中创建的实例
- 单例类:
public class Boss {
//静态变量在类的所有对象中只有一份
private static Boss boss = new Boss();
private Boss() {
}
public static Boss getBossInstance() {
return boss;
}
}
- 测试代码:
public static void main(String[] args) throws IOException {
Boss boss1 = Boss.getBossInstance();
Boss boss2 = Boss.getBossInstance();
System.out.println(boss1 == boss2);
}
懒汉式
- 构造方法私有化
- 提供一个静态的当前类的实例(不实例化)
- 提供一个静态方法,在该方法中当2中的实例为null时实例化,最后返回这个实例
- 单例类:
public class Boss {
//静态变量在类的所有对象中只有一份
private static Boss boss;
private Boss() {
}
public static Boss getBossInstance() {
if (boss == null) {
boss = new Boss();
}
return boss;
}
}
- 测试代码:
public static void main(String[] args) throws IOException {
Boss boss1 = Boss.getBossInstance();
Boss boss2 = Boss.getBossInstance();
System.out.println(boss1 == boss2);
}
懒汉式存在的问题
因为程序是以抢占CPU的方式运行的,所以懒汉式有可能会出现问题,示意代码:
-
单例类:
public class Boss {//懒汉式 private static Boss boss; private Boss() { } public static Boss getBossInstance() { if (boss == null) { //--------------1 程序执行到此处因为下面代码休眠,CPU易被别人抢占 try {//程序休息,别人更容易抢到CPU Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } boss = new Boss(); } return boss; } }
-
测试代码:
public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { Boss boss1 = Boss.getBossInstance(); System.out.println(boss1); } }).start(); new Thread(() -> { Boss boss2 = Boss.getBossInstance(); System.out.println(boss2); }).start(); }
程序运行结果:
-
实体类
public class Boss {//懒汉式:双重检查加锁 private volatile static Boss boss; private Boss() { } public static Boss getBossInstance() { if (boss == null) { //先判断是否为空再加锁 synchronized ( Boss.class){ //加锁 try {//程序休息,别人更容易抢到CPU Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } if(boss == null) { boss = new Boss(); } } } return boss; } }
-
测试代码1
public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { Boss boss1 = Boss.getBossInstance(); System.out.println(boss1); } }).start(); new Thread(() -> { Boss boss2 = Boss.getBossInstance(); System.out.println(boss2); }).start(); }
-
测试代码2
public class B1 {
public static void fun() {
Boss boss = Boss.getInstance();
System.out.println(boss);
}
}
public class B2 {
public static void fun() {
Boss boss = Boss.getInstance();
System.out.println(boss);
}
}
public class B {
public static void main(String[] args) {
B1.fun();
B2.fun();
}
}