所谓单利模式,即只能开启一个线程,只有一个实例,并且能够实现自我实例化,主要分为懒汉式和饿汉式。
(1)饿汉式
所谓饿汉式,就好比一个饿汉饿了好久,然后某一天到了餐厅,由于饿了很久,所以进入餐厅就希望所有的食物都已经准备好然后直接吃就可以。在程序中就相当于我们提前创建好了一个对象,类加载的时候就实例化并且创建对象,后续就可以直接拿来用,但是这也有个缺点,就是不管需不需要,他都会自动实例化创建对象,在一些情况下会造成资源的浪费。在线程安全方面,由于饿汉式在线程还没出现之前就已经实例化了,因此饿汉式线程一定是安全的。
package com.example.mzz.singleInstance;
/**
* 饿汉式
*/
public class SingleInstanceDemo01 {
public static void main(String[] args) {
//因为是单例模式,只有一个实例,不妨创建两个实例来看一下这两个实例指向是否一样,
// 如果一样则说明只创建了一个实例,是单例模式
SingleInstance instance1 = SingleInstance.getInstance(); //静态成员变量可以直接类.方法来调用
SingleInstance instance2 = SingleInstance.getInstance();
System.out.println(instance1 == instance2);
}
}
class SingleInstance{
//创建一个静态成员变量用来存储对象
public static final SingleInstance ins = new SingleInstance();
//因为是单例模式,只能有一个对象,所以我们需要将构造器私有化
private SingleInstance(){
}
//写一个方法,返回该对象
public static SingleInstance getInstance(){
return ins;
}
}
运行结果:
可以看到,结果为true,说明确实只创建了一个实例,是单例模式。
(2)懒汉式
懒汉式与饿汉式相反,在类加载的时候,不会实例化对象,而是在外部什么时候调用什么时候new对象。由于懒汉式加载是在使用时才会去new 实例的,new的时候是一个动态的过程,是放到方法中实现的,如果有多个线程去访问这个实例,但是这个实例还在new,这时候有多少线程就会new出多少个实例,一个方法return一个实例,最终会返回哪个实例不确定,这就使得线程不安全,所以可以通过加一个同步锁synchronized关键字来实现。
package com.example.mzz.singleInstance;
public class SingleInstanceDemo02 {
public static void main(String[] args) {
SingleInstance02 instance1 = SingleInstance02.getIns(); //静态成员变量可以直接类.方法来调用
SingleInstance02 instance2 = SingleInstance02.getIns();
System.out.println(instance1 == instance2);
}
}
class SingleInstance02{
public static SingleInstance02 ins; //类加载的时候不会实例化创建对象
//构造器私有化
private SingleInstance02() {
}
public static synchronized SingleInstance02 getIns(){
//先判断ins是否为null,如果没有,则new一个对象
if(ins == null){
ins = new SingleInstance02();
}
return ins;
}
}
运行结果:
可以看到,结果为true,说明确实只创建了一个实例,是单例模式。
比较:
1.懒汉式相比较饿汉式而言需要加锁,效率低
2.饿汉式不管是否需要创建对象,在类加载的时候都会实例化创建对象,比懒汉式浪费空间