Java设计模式 - 单例模式

特点:

    1. 一个类只能有一个对象实例

步骤

    1. 构造器私有化 – 外部不能创建对象
    1. 声明一个私有的本类的静态属性对象
    1. 创建一个公共的静态方法访问本类的静态属性对象

1. 懒汉式

1.1 懒汉式 – 需要在生成单例对象 – 线程不安全
class Threa1 extends Thread {
	@Override
	public void run() {
		System.out.println(Student.getStudent());
	}
}

class Student {
	private static Student student;
	
	private Student() {}
	
	public static Student getStudent() {
		if(student == null) {
			return ( student = new Student() );
		}
		return student;
	}
}

//-----------------------------
//测试代码
public static void main() {
		System.out.println("线程不安全 - 多线程");
		Thread getObject1 = new Threa1();
		Thread getObject2 = new Threa1();
		getObject1.start();
		getObject2.start();
		
		System.out.println("\n\n");
		
		System.out.println("线程不安全 - 单线程");
		System.out.println(Student.getStudent());
		System.out.println(Student.getStudent());
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1oLrLgIG-1574792544081)(en-resource://database/10703:1)]

1.2 懒汉式 – 需要在生成单例对象 – 线程安全–单检查
class Threa1 extends Thread {
	@Override
	public  void run() {
		System.out.println(Student.getStudent());
	}
}

class Student {
	private static Student student;
	
	private Student() {}
    
    // 这句跟下面的注释代码是一样的,都是静态同步方法都是锁 Student.class对象
	public synchronized static Student getStudent() {
		if(student == null) {
			return ( student = new Student() );
		}
		return student;
	}
    
/*    public static Student getStudent() {
        synchronized( Student.class ) {
            if(student == null) {
                return ( student = new Student() );
            }
            return student;
        }
	}
*/
    
}

//-----------------------------
//测试代码
public static void main() {
		System.out.println("线程安全 - 多线程");
		Thread getObject1 = new Threa1();
		Thread getObject2 = new Threa1();
		getObject1.start();
		getObject2.start();
		
		System.out.println("\n\n");
		
		System.out.println("线程安全 - 单线程");
		System.out.println(Student.getStudent());
		System.out.println(Student.getStudent());
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a9rY4SDz-1574792544084)(en-resource://database/10705:1)]

1.3 懒汉式 – 需要在生成单例对象 – 线程安全–双重检查

注意: 对象获取锁非常耗资源,我们尽可能减少不必要的获取锁

class Student {
	private static Student student;
	
	private Student() {}
	
	public static Student getStudent1() {
	    synchronized( Student.class ) {
            if(student == null) {
                return ( student = new Student() );
            }
            return student;
        }
	}
    	
	public static Student getStudent2() {
	    if( student == null ) {
            synchronized( Student.class ) {
                if(student == null) {
                    return ( student = new Student() );
                }

            }
        }
        return student;
	}
}

推导为什么 getStudent2() 的性能比 getStudent1() 性能高 ?
  1. 假设有 100个线程同时进行访问 静态getStudentn() 方法

  2. 当线程run, 都调用getStudent1() – 则100个线程在运行的时候都需要获得同步锁。
  3. 当线程run, 都调用getStudent2() – 则可能有几个线程在运行的时候获得锁,而其他因为知道已经有单例对象,而直接返回单例对象,无需在获得同步锁。

2. 饿汉式 – 已经是线程安全

2.1 使用时单例加载

  

class Student2 {
	private static final Student2 student = new Student2();
	
	private Student2() {
		
	}
	
	public Student2 getStudent() {
		return student;
	}
		
}

2.2 调用getStudent()时单例才加载

注意类只有使用的时候才加载二进制文件进入内存

class Student3 {
	
	private static class Inner{
		private static Student3 student = new Student3();
	}
	
	private Student3() {}
	
    // 1. 当有线程调用该方法时,才会由静态内部类Inner创建初始化单例对象
	public Student3 getStudent() {
		return Inner.student;
	}
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值