单例模式
顾名思义,使这个类在全局只有一个实例,单例模式的写法很多,讨论一下这些写法,spring也有个单例的注解,它是怎么实现的呢?
网上的多种实现方式
懒汉式一
public class TestLazyMan{
public static void main(String[] args){
new Thread(new TestMutiType()).start();
new Thread(new TestMutiType()).start();
}
}
class TestMutiType implements Runnable{
@Override
public void run() {
LazyMan instance = LazyMan.getInstance();
System.out.println(instance);
}
}
class LazyMan {
private static LazyMan lazyMan;
private LazyMan(){
}
public static LazyMan getInstance(){
if(lazyMan == null){
lazyMan = new LazyMan();
}
return lazyMan;
}
}
print:
/*这里的结果 有时是一样的,有时不一样*/
designpatterns.singleton.LazyMan@5bdbaa31
designpatterns.singleton.LazyMan@7dfa4e7
这种实现方式有线程安全问题,多线程情况下不要用
懒汉式二
public class TestLazyMan{
public static void main(String[] args){
new Thread(new TestMutiType()).start();
new Thread(new TestMutiType()).start();
}
}
class TestMutiType implements Runnable{
@Override
public void run() {
LazyMan instance = LazyMan.getInstance();
System.out.println(instance);
}
}
class LazyMan {
private static LazyMan lazyMan;
private LazyMan(){
}
public static synchronized LazyMan getInstance(){
if(lazyMan == null){
lazyMan = new LazyMan();
}
return lazyMan;
}
}
print:
designpatterns.singleton.LazyMan@2b282c31
designpatterns.singleton.LazyMan@2b282c31
加上synchronized保证了线程安全
饿汉式
public class TestHungryMan {
public static void main(String[] args){
new Thread(new MultiType()).start();
new Thread(new MultiType()).start();
}
}
class MultiType implements Runnable{
@Override
public void run() {
HungryMan instance = HungryMan.getInstance();
System.out.println(instance);
}
}
class HungryMan{
private static HungryMan hungryMan = new HungryMan();
private HungryMan(){}
public static HungryMan getInstance(){
return hungryMan;
}
}
print:
designpatterns.singleton.HungryMan@4336eeed
designpatterns.singleton.HungryMan@4336eeed
看起来不错,但我觉得这种实现实际上是在投机取巧,当我们需要一个实例时,也许像要在它初始化去做一些事情,如果将他放到类加载时来做单例,那它还可以做一些我们的事情吗,是不是所有的事情都要被牵扯到类加载时去做。
双重校验锁
public class TestDoubleCheck {
public static void main(String[] args){
new Thread(new MultiDoubleCheck()).start();
new Thread(new MultiDoubleCheck()).start();
}
}
class MultiDoubleCheck implements Runnable{
@Override
public void run() {
DoubleCheck instance = DoubleCheck.getInstance();
System.out.println(instance);
}
}
class DoubleCheck{
private volatile static DoubleCheck doubleCheck;
private DoubleCheck(){}
public static DoubleCheck getInstance(){
if(doubleCheck == null){
synchronized (DoubleCheck.class){
if(doubleCheck == null){
doubleCheck = new DoubleCheck();
}
}
}
return doubleCheck;
}
}
print:
designpatterns.singleton.DoubleCheck@782b1823
designpatterns.singleton.DoubleCheck@782b1823
有一个需要注意的点:实例加了volatile关键字,如果不加这个关键字会发生什么呢?
如果编译器初始化时重排序了,那么有可能当这个单例还没有初始化完成,就被另一个线程拿去用了
静态内部类式
public class TestStaticInner {
public static void main(String[] args){
new Thread(new TestMultiStaticInner()).start();
new Thread(new TestMultiStaticInner()).start();
}
}
class TestMultiStaticInner implements Runnable{
@Override
public void run() {
StaticInner instance = StaticInner.getInstance();
System.out.println(instance);
}
}
class StaticInner{
private static class StaticInnerHolder{
private static final StaticInner instance = new StaticInner();
}
private StaticInner(){}
public static StaticInner getInstance(){
return StaticInnerHolder.instance;
}
}
好,项目里目前用的都是这种,既不主动,又不被动
spring的实现方式
挖个坑先,以后再填