单例模式的几种实现方式
程序员文章站
2022-06-27 23:33:43
1)饿汉式 public class Person{ // 私有的构造方法 private Person{} /* private Person person = new Person(); 出现*Error错误 因为创建对象需要调用构造方法执行 构造方法执行在栈内存中 每次创建对象需要加载属性 该属性又是当前类对象 造成无限循环创建对象 最终栈内存压满 不释放...
1)饿汉式
public class Person{
// 私有的构造方法
private Person{}
/* private Person person = new Person();
出现*Error错误 因为创建对象需要调用构造方法执行
构造方法执行在栈内存中 每次创建对象需要加载属性 该属性又是当前类对象
造成无限循环创建对象 最终栈内存压满 不释放
栈内存的空间比堆内存要小 所以栈内存先堆满
因此需要加static修饰符 static修饰的元素属于类 只加载一次
*/
//final 修饰的属性基本类型是值不能改变 引用类型是地址不能改变 防止用户拿到对象 将对象置为null
//私有的当前类对象作为属性
private static final Person person = new Person();
// 公有的方法 用来获取该类对象
/*
static 调该方法的两种方式
1)类名点(方法需要static修饰)
2)对象点(该方法用来获取当前类对象 此时还没有对象)
*/
public static Person getPerson(){
return person;
}
}
2)双重if检测模型
public class Person{
// 私有构造方法
private Person{}
/*
valatile 修饰属性 有以下几个特点:
1. 属性在某一个线程操作的时候 属性是锁定的 其他的线程没法获取属性
2. 属性被某一个线程修改后 另外的线程立即可见
3. 可以禁止指令重新排布
当被volatile修饰后 堆必须先分配一个对象内存 必须再将对象内存的地址交给栈引用 最后往对象空间中摆放东西
没有volatile修饰时 可能会产生摆放东西时又来了一个对象 而此时并没有将地址引用交给栈
*/
private static volatile Person person;
// 公有静态方法 获取该类对象
public static Person getPerson(){
if(person == null){
// 锁定当前类
synchronized (Person.class){
// 锁定时多线程并发 两个线程经过第一次判断都为null 当一个线程要锁还没锁的时候 另一个线程却锁住了 new出了对象
// 而此时没锁住的那个线程这个时候再锁 此时对象已经有了 所以需要再进行一次判断
if(person == null){
person = new Person();
}
}
}
return person;
}
}
3)枚举实现单例
*序列化、线程安全(枚举本身是线程安全的)
public enum Person{
PERSONONE;
public Person getInstance(){
return Person.PERSONONE;
}
}
4)static代码块实现单例模式
public class Person {
private Person(){}
private static final Person PERSON;
static {
PERSON = new Person();
}
public static Person getInstance(){
return PERSON;
}
}
5)静态内部类实现
public class Person {
private Person(){}
private static class Holder{
private static final Person person = new Person();
}
public static Person getInstance(){
return Holder.person;
}
}
拓展
静态内部类加载顺序问题
public class Test {
public static void main(String[] args) {
new A.C();
//内部类静态属性p2 内部类静态块 内部类属性p1 内部类属性p3 内部类普通块 内部类构造
}
}
class A {
private P p1 = new P("A类属性p1");
static P p3 = new P("A类静态属性p2");
public A() {
System.out.println("A类构造方法");
}
private P p2 = new P("A类属性p3");
static {
System.out.println("A类静态块");
}
{
System.out.println("A类普通块");
}
public static class C {
private P p1 = new P("内部类属性p1");
static P p2 = new P("内部类静态属性p2");
public C() {
System.out.println("内部类构造");
}
private P p3 = new P("内部类属性p3");
static {
new P("内部类静态块");
}
{
new P("内部类普通块");
}
}
}
class P {
public P(String s) {
System.out.println(s);
}
}
本文地址:https://blog.csdn.net/weixin_45555680/article/details/111877074