1、单例模式的实现方式
java
/**
* 1、饿汉模式
*/
public class Singleton1 {
private static AtomicInteger count = new AtomicInteger(0);
private static final Singleton1 instance = new Singleton1();
public static Singleton1 getInstance(){
return instance;
}
}
java
/**
* 2、懒汉模式
*/
public class Singleton2 {
private static AtomicInteger count = new AtomicInteger(0);
private static Singleton2 instance = null;
private Singleton2(){}
public static Singleton2 getInstance(){
if(instance == null){
count.incrementAndGet();
instance = new Singleton2();
}
return instance;
}
public static int getCount(){
return count.get();
}
}
java
/**
* 3、不安全的锁
*/
public class Singleton3 {
private static AtomicInteger count = new AtomicInteger(0);
private static Singleton3 instance = null;
public static Singleton3 getInstance(){
if(instance == null){
synchronized (Singleton3.class){
count.incrementAndGet();
instance = new Singleton3();
}
}
return instance;
}
private Singleton3(){}
public static int getCount(){
return count.get();
}
}
java
/**
* 4、不安全的锁 volatile
*/
public class Singleton4 {
private static AtomicInteger count = new AtomicInteger(0);
private static volatile Singleton4 instance = null;
public static Singleton4 getInstance(){
if(instance == null){
count.incrementAndGet();
instance = new Singleton4();
}
return instance;
}
private Singleton4(){}
public static int getCount(){
return count.get();
}
}
java
/**
* 5、双重校验锁
*/
public class Singleton5 {
private static AtomicInteger count = new AtomicInteger(0);
private static Singleton5 instance = null;
public static Singleton5 getInstance(){
if(instance == null){
synchronized (Singleton5.class){
if(instance == null){
count.incrementAndGet();
instance = new Singleton5();
}
}
}
return instance;
}
private Singleton5(){}
public static int getCount(){
return count.get();
}
}
java
/**
* 6、spring静态工厂生成单例对象,单例注册表
*/
public class Singleton6{
private static AtomicInteger count = new AtomicInteger(0);
private static HashMap<String, Object> registry = new HashMap<>();
static {
Singleton6 instance = new Singleton6();
registry.put(instance.getClass().getName(), instance);
}
public static Singleton6 getInstance(String name){
if(name == null){
name = "com.xf.singleton.Singleton6";
}
if(registry.get(name) == null){
try {
count.incrementAndGet();
registry.put(name, Class.forName(name).newInstance());
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
return (Singleton6) registry.get(name);
}
public static int getCount(){
return count.get();
}
}
2、spring中的单例实现方式
java
/**
* 使用了单例注册列表
*/
public abstract class AbstractBeanFactory implements ConfigurableBeanFactory {
/**
* 充当了Bean实例的缓存,实现方式和单例注册表相同
*/
private final Map singletonCache = new HashMap();
public Object getBean(String name)throws BeansException {
return getBean(name, null, null);
}
// ...
public Object getBean(String name, Class requiredType, Object[] args)throws BeansException {
//对传入的Bean name稍做处理,防止传入的Bean name名有非法字符(或则做转码)
String beanName = transformedBeanName(name);
Object bean = null;
//手工检测单例注册表
Object sharedInstance = null;
//使用了代码锁定同步块,原理和同步方法相似,但是这种写法效率更高
synchronized (this.singletonCache) {
sharedInstance = this.singletonCache.get(beanName);
}
if (sharedInstance != null) {
// ...
//返回合适的缓存Bean实例
bean = getObjectForSharedInstance(name, sharedInstance);
} else {
// ...
//取得Bean的定义
RootBeanDefinition Invalid timestamp = getMergedBeanDefinition(beanName, false);
// ...
//根据Bean定义判断,此判断依据通常来自于组件配置文件的单例属性开关
//<bean id="date" class="java.util.Date" scope="singleton"/>
//如果是单例,做如下处理
if (mergedBeanDefinition.isSingleton()) {
synchronized (this.singletonCache) {
//再次检测单例注册表
sharedInstance = this.singletonCache.get(beanName);
if (sharedInstance == null) {
// ...
try {
//真正创建Bean实例
sharedInstance = createBean(beanName, mergedBeanDefinition, args);
//向单例注册表注册Bean实例
addSingleton(beanName, sharedInstance);
} catch (Exception ex) {
// ...
} finally {
// ...
}
}
}
bean = getObjectForSharedInstance(name, sharedInstance);
}
//如果是非单例,即prototpye,每次都要新创建一个Bean实例
//<bean id="date" class="java.util.Date" scope="prototype"/>
else {
bean = createBean(beanName, mergedBeanDefinition, args);
}
}
// ...
return bean;
}
}
spring中的单例不是线程安全的,当涉及到共享数据时需要记性多线程安全性的处理