您的位置:首页 > 编程语言 > Java开发

Java 单例模式之饿汉模式 懒汉模式

2017-11-07 18:24 417 查看
单例模式有以下特点:

1. 单例类只能有一个实例。

2. 单例类必须自己创建自己的唯一实例。

3. 单例类必须给所有其他对象提供这一实例。

单例模式确保某个类只有一个实例。

单例模式实现有两种方式:

1. 饿汉模式

public class HungrySingle {
//这里方法均为static,其他类可直接使用。
private static final HungrySingle single = new HungrySingle();
private HungrySingle(){}
//如果自己不创建构造方法,会自动创建无参public构造方法
public static HungrySingle getInstance(){
return single;
}
}


测试:

public class HungrySingle {
//这里方法均为static,其他类可直接使用。
private static final HungrySingle single = new HungrySingle();
private HungrySingle(){}
//如果自己不创建构造方法,会自动创建无参public构造方法
public static HungrySingle getInstance(){
return single;
}

public static void main(String[] args){
HungrySingle a = getInstance();
System.out.println(a);
a = getInstance();
System.out.println(a);
a = getInstance();
System.out.println(a);
}
}


运行结果:



可以看到返回的是同一个实例。

饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。

2. 懒汉模式

双重校验锁式

public class LazySingle {

private volatile static LazySingle single;

private LazySingle(){}

public static LazySingle getInstance(){
if(single == null){
synchronized (LazySingle.class) {
//对类对象加锁,所有对象均不能同时运行。
if(single == null){
single = new LazySingle();
}
}
}
return single;
}
}


测试

package Test;

public class LazySingle {

private volatile static LazySingle single;

private LazySingle(){}

public static LazySingle getInstance(){
if(single == null){
synchronized (LazySingle.class) {
if(single == null){
single = new LazySingle();
}
}
}
return single;
}

public static void main(String[] args) {
LazySingle single = getInstance();
System.out.println(single);
single = getInstance();
System.out.println(single);
single = getInstance();
System.out.println(single);
}
}


运行结果:



也可写成下边这种形式,但每次都需要加锁,释放锁,效率低。

public class LazySingle {

private static LazySingle single;

private LazySingle(){}

public static LazySingle getInstance(){
synchronized (LazySingle.class) {
if(single == null){
single = new LazySingle();
}
return single;
}
}
}


下面这种懒汉模式在多线程下,有可能创建出多个实例。所以不对。线程不安全

public class LazySingle {

private static LazySingle single;

private LazySingle(){}

public static LazySingle getInstance(){
if(single == null){
single = new LazySingle();
}
return single;
}
}


测试:

package Test;

class multiSingle implements Runnable{
@Override
public void run() {
LazySingle single = LazySingle.getInstance();
System.out.println(single);
}
}

public class LazySingle {

private static LazySingle single;

private LazySingle(){}

public static LazySingle getInstance(){
if(single == null){
for(int i = 0; i < 100000; ++i){
i++;
i--;
}
single = new LazySingle();
}
return single;
}

public static void main(String[] args) {

for(int i = 0; i < 100; ++i){
new Thread(new multiSingle()).start();
}

}

}


运行结果:



可以看到创建了多个实例。

3.懒汉模式-静态内部类写法

这种方式能达到双检锁方式一样的功效,但实现更简单。这种方式利用了 ClassLoader 机制来保证初始化 instance 时只有一个线程,从而保证线程安全。

这种方式当 LazySingle 类被装载了,instance 不一定被初始化。因为 SingleHolder 类没有被主动使用,只有显式通过调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance,实现懒加载。

public class LazySingle {
private static class SingleHolder{
private static final LazySingle instance = new LazySingle();
}
private LazySingle() {}
public static LazySingle getInstance() {
return SingleHolder.instance;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: