单例模式就是采用一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。
JDK中,java.lang.Runtime就是经典的单例模式(饿汉式)。
public class SingletonTest01 {
// 私有化SingletonTest01使其无法被new
private SingletonTest01() {
}
private final static SingletonTest01 instance = new SingletonTest01();
public static SingletonTest01 getInstance(){
return instance;
}
}
方式可用但可能造成内存浪费
public class SingletonTest02 {
private SingletonTest02() {
}
private static SingletonTest02 instance;
static {
instance = new SingletonTest02();
}
public static SingletonTest02 getInstance(){
return instance;
}
}
也可能造成内存浪费
public class SingletonTest03 {
private SingletonTest03() {
}
private static SingletonTest03 instance;
// 用到该方法时 才去创建
public static SingletonTest03 getInstance(){
if(instance == null){
instance = new SingletonTest03();
}
return instance;
}
}
如果在多线程下,多个线程同时进入这个判断语句就会产生多个实例,所以多线程环境下不可使用这种方式
public class SingletonTest04 {
private SingletonTest04() {
}
private static SingletonTest04 instance;
// 用到该方法时 才去创建
public static synchronized SingletonTest04 getInstance(){
if(instance == null){
instance = new SingletonTest04();
}
return instance;
}
}
解决了线程安全问题,但是效率太低了,每个线程想获得实例时,执行getInstance()方法时都要进行同步
实际开发中不推荐
本意是想对第四种同步方法进行优化,但还是可以有多条线程进入if判断语句,所以线程并不安全
不能使用
public class SingletonTest05 {
private SingletonTest05() {
}
private static volatile SingletonTest05 instance;
public static synchronized SingletonTest05 getInstance(){
if(instance == null){
synchronized (SingletonTest05.class){
if(instance == null){
instance = new SingletonTest05();
}
}
}
return instance;
}
}
好处就在于进行了两次if(singleton == null)检查,保证线程安全,实例化代码只用执行一次,后面再次访问时外层if判断避免了反复的方法同步
线程安全;延迟加载;效率高;在实际开发中推荐使用这种单例模式
public class SingletonTest06 {
private SingletonTest06() {
}
private static class SingletonInstance{
private static final SingletonTest06 INSTANCE = new SingletonTest06();
}
public static synchronized SingletonTest06 getInstance(){
return SingletonInstance.INSTANCE;
}
}
采用了类装载的机制来保护初始化实例时只有一个线程,静态内部类在类装载的时候不会实例化,而是在需要实例化的时,调用getInstance方法,才会装载SingletonInstance类,类的静态属性指挥在第一次加载时初始化,所以JVM帮我们保证了线程的安全性,类初始化时,别的线程时无法进入的。
避免了线程不安全,利用静态内部类特点实现延迟加载,效率高推荐使用
public enum SingletonTest07 {
INSTANCE;// 属性
public void sayOK(){
System.out.println("ok");
}
}
原文:https://www.cnblogs.com/wdaa/p/14417455.html