JAVA 与 MyCat(2) 单例模式

本文通过Mycat的实例化过程介绍了Java中单例模式的不同实现方式,包括饿汉模式、懒汉模式及其变种,并分析了各自的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过mycat来学习java了^^。


接前一篇:http://blog.youkuaiyun.com/john_chang11/article/details/78668667


MycatServer server = MycatServer.getInstance();

获取MyCat实例,其实就是读取配置文件,并验证正确性等。

MyCat实例必须全局唯一,所以这里涉及到JAVA的单实例模式,就是一个类只有唯一一个实例对象存在。先来看看mycat源码是怎么做的:

public class MycatServer {
	private static final MycatServer INSTANCE = new MycatServer();
	
	public static final MycatServer getInstance() {
		return INSTANCE;
	}

	private MycatServer() {
		......
	}
}

首先,将构造方法定义成私有的,这样外界不能再实例化该类。然后,提供一个公有的静态方法,使外界只能通过该方法来获取类实例,该方法返回一个类型为类本身的静态属性值,该属性值在类加载时调用私有构造方法初始化。这就保障了,该类只有唯一一个实例对象的存在。

上面这种写法是单实例创建的饿汉模式,线程安全,但浪费内存空间,不过mycat要运行MycatServer类是肯定要装载的,所以源码里这样用也没有问题。单实例模式的写法还有别的写法,一起看看。


1.懒汉,省内存空间,但线程不安全,不推荐使用

public class Singleton {
    private static Singleton instance=null;
    private Singleton(){
        
    }
    public static Singleton getInstance(){
        if(instance==null){
            instance=new Singleton();
        }
        return instance;
    }
}

使用时才初始化实例,所以省内存,但也影响了速度,而且线程不安全,只能在单线程环境下可行,不推荐使用。


2.懒汉,线程安全,但效率低,不推荐使用

public class Singleton {
    private static Singleton instance=null;
    private Singleton(){
        
    }
    public static synchronized Singleton getInstance(){
        if(instance==null){
            instance=new Singleton();
        }
        return instance;
    }
}

这种方式也是在使用时才初始化,省内存,但每次调用getInstance()方法时,都需要获取同步锁,非常耗时,也不推荐使用。


3.懒汉,双重检查锁,依然有问题,不推荐使用

public class Singleton {
    private static Singleton instance=null;
    private Singleton(){
        
    }
    public static Singleton getInstance(){
        if(instance==null){
            synchronized(Singleton.class){
                if(instance==null){
                    instance=new Singleton();
                }
            }
        }
        return instance;
    }
}

这种方式是对第2种的改进,只在第一次创建实例时需要同步锁,以后不再需要,大大提高了性能。但是这种方式依然有问题,这与JAVA内存模式的无序写入有关,即使使用volatile,也依然有问题。为了不偏离主题,本文不详细介绍这些问题的原因,有兴趣可以参考:http://blog.youkuaiyun.com/chenchaofuck1/article/details/51702129http://blog.youkuaiyun.com/axman/article/details/1089196

4.饿汉,线程安全,效率高,但内存使用率低,推荐使用

public class Singleton {
    private static Singleton instance=new Singleton();
    private Singleton(){
        
    }
    public static Singleton getInstance(){
        return instance;
    }
}

这种方式,是利用JVM的机制:静态实例的初始化是ClassLoader经由[ThreadSafe]来完成,所以是线程安全的。该方法去除的同步,且类加载时就创建实例,所以效率高。但由于是类加载时就创建实例,所以内存使用率低,不过既然使用该类一般就会初始化该类的一个实例,所以该仍然推荐使用。


5.静态内部类,集所有优点于一身,推荐使用

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

内部类不会随主类加载而加载,只有在第一次使用时才会加载,而单实例又是内部类的静态实例,所以用这种方式获取单实例,即是lazy loading,节省内存,又是线程安全且不需要同步锁的。所以用这种方式获取单实例最好。不过,使用时才创建实例,会对第一次调用产生影响,所以这种方式与第4种方式,可以互补使用:如果单实例类一定需要初始化,就用第4种,如果不一定需要初始化,就用第5种。










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值