单例模式的实现有很多种,这里我们在代码实现上来完成常见的几种。
1. 双重检索
package day01;
/**
* 单例模式的实现方式:1.双重检索
*
* @author WEI 哥
*
*/
public class Fibonacci {
//私有化构造方法,避免外部创建对象
private Fibonacci() {}
//使用volatile避免多线程下指令重排
private volatile static Fibonacci fi=null;
public static void main(String[] args){
CheckThread ct=new CheckThread();
ct.setName("线程一");ct.start();
CheckThread ct2=new CheckThread();
ct2.setName("线程二");ct2.start();
CheckThread ct3=new CheckThread();
ct3.setName("线程三");ct3.start();
CheckThread ct4=new CheckThread();
ct4.setName("线程四");ct4.start();
}
/*
* 双重检索
*/
public static Fibonacci getInstance() {
if(fi==null) {
//给该类加锁,避免多线程情况下出现不同线程同时创建对象
synchronized (Fibonacci.class) {
if(fi==null) {
fi= new Fibonacci();
}
}
}
return fi;
}
}
/*
* 多线程调用
*/
class CheckThread extends Thread{
public void run() {
System.out.println(Thread.currentThread().getName()+Fibonacci.getInstance());
}
}
2. 静态内部类
package day01;
/**
* 单例模式的实现方式:2.静态内部类
*
* @author WEI 哥
*
*/
public class Fibonacci {
//私有化构造方法,避免外部创建对象
private Fibonacci() {}
public static void main(String[] args){
CheckThread ct=new CheckThread();
ct.setName("线程一");ct.start();
CheckThread ct2=new CheckThread();
ct2.setName("线程二");ct2.start();
CheckThread ct3=new CheckThread();
ct3.setName("线程三");ct3.start();
CheckThread ct4=new CheckThread();
ct4.setName("线程四");ct4.start();
}
/*
* 静态内部类
*/
public static class getInstance{
private static final Fibonacci fi=new Fibonacci();
}
/*
* 提供访问方法
*/
public static Fibonacci getFi() {
return getInstance.fi;
}
}
/*
* 多线程调用
*/
class CheckThread extends Thread{
public void run() {
System.out.println(Thread.currentThread().getName()+Fibonacci.getFi());
}
}
3.采用枚举类:
package day01;
/*
* Test继承自java.lang.Enum,故不能继承其他的类,
* 反编译的结果是:public static final day01.Test fi;
*/
public enum Test {
fi;
}
package day01;
/**
* 单例模式的实现方式:3.枚举
*
* @author WEI 哥
*
*/
public class Fibonacci{
public static void main(String[] args) {
Test test=Test.fi;
Test test1=Test.fi;
Test test2=Test.fi;
System.out.println(test.getDeclaringClass().getName()+" "+test1.getDeclaringClass().getName()+" "+test2.getDeclaringClass().getName());
}
}