饿汉式:
所谓饿汉式,就是在程序启动或单例模式类被加载的时候,单例模式实例就已经被创建。可能不会使用这个对象,这就造成了浪费。
package com.zhb.classloader;
public class HungrySingleton {
private HungrySingleton() {
}
private static HungrySingleton instance;
static {
instance = new HungrySingleton();
}
public static HungrySingleton getInstance() {
return instance;
}
}
验证饿汉式:
package com.zhb.classloader;
public class HungrySingleton {
public int count=0;
private HungrySingleton() {
System.out.println(Thread.currentThread().getName()+"\t 我是构造方法HungrySingleton()");
}
private static HungrySingleton instance;
static {
instance = new HungrySingleton();
}
public static HungrySingleton getInstance() {
return instance;
}
public static void main(String[] args) throws InterruptedException {
// for (int i = 0; i < 20; i++) {
// Thread thread = new Thread(new Runnable() {
// @Override
// public void run() {
// HungrySingleton.getInstance();
// }
// });
// thread.start();
// }
System.out.println("123");
}
}
输出:
![](https://img.haomeiwen.com/i5679451/64fc0c1a059cbb5a.png)
可以看到,我们在main函数中没有去显示调用getInstance,但是却生成了单例对象。
为什么这样能实现单例模式呢?
因为调用类的静态方法会导致类的初始化,就会导致对静态变量的初始化和执行静态代码块的工作。在类的生命周期中,初始化只会进行一次。所以可以保证只会new 一个对象。上例中,虽然没有执行getInstance(),但是有这样一条规则:
当虚拟机执行一个main方法时,会首先初始化main所在的这个主类。所以会初始化单例模式类。
改进:
饿汉式单例类不能实现延迟加载,不管将来用不用始终占据内存;
使用Initialization Demand Holder (IoDH)的技术解决饿汉的问题。
package com.zhb.classloader;
public class IODHsingleton {
private IODHsingleton() {
System.out.println("初始化");
}
//静态内部类
private static class SingletonClass {
//私有静态常量实例
private static final IODHsingleton instance = new IODHsingleton();
}
public static IODHsingleton getInstance() {
//调用内部类的静态字段,此时内部类初始化
return SingletonClass.instance;
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 20; i++) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
IODHsingleton.getInstance();
}
});
thread.start();
}
//System.out.println("123");
}
}
这种方式只有刚调用getInstance时,才会去触发SingletonClass 的初始化,从而产生单例对象。
输出:
![](https://img.haomeiwen.com/i5679451/fbec1e60f2b5c606.png)
20个线程同时去调用getInstance,最终只打印出一句初始化,证明是单例对象。
网友评论