在MyCat的源码中,很多对象都使用到了单例模式。
首先是MycatServer类,该实例必须全局唯一,所以这里涉及到JAVA的单实例模式,就是一个类只有唯一一个实例对象存在。先来看看mycat源码是怎么做的:
public class MycatServer { private static final MycatServer INSTANCE = new MycatServer(); public static final MycatServer getInstance() { return INSTANCE; } private MycatServer() { ...... } }
public final class MycatStartup { public static void main(String[] args) { MycatServer server = MycatServer.getInstance(); } }
首先,将构造方法定义成私有的,这样外界不能再实例化该类。然后,提供一个公有的静态方法,使外界只能通过该方法来获取类实例,该方法返回一个类型为类本身的静态属性值,该属性值在类加载时调用私有构造方法初始化。这就保障了,该类只有唯一一个实例对象的存在。
上面这种写法是单实例创建的饿汉模式,线程安全,但浪费内存空间,不过mycat要运行MycatServer类是肯定要装载的,所以源码里这样用也没有问题。
还有一种静态内部类单例实现方式,集所有优点于一身,推荐使用:
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,节省内存,又是线程安全且不需要同步锁的。所以用这种方式获取单实例最好。
参考文章:https://blog.csdn.net/john_chang11/article/details/78679867
另外,在Mycat的源码中有很多地方都使用到了饿汉式的单例模式,比如ZkConfig:
public class ZkConfig { private ZkConfig() { } private static ZkConfig ZKCFGINSTANCE = new ZkConfig(); public static ZkConfig getInstance() { return ZKCFGINSTANCE; } public void initZk(){ //... } }
public final class MycatStartup { public static void main(String[] args) { //use zk ? ZkConfig.getInstance().initZk(); } }
还有下面几个类:
public class TableStatAnalyzer implements QueryResultListener { private final static TableStatAnalyzer instance = new TableStatAnalyzer(); private TableStatAnalyzer() {} public static TableStatAnalyzer getInstance() { return instance; } }
public class QueryConditionAnalyzer implements QueryResultListener { private final static QueryConditionAnalyzer instance = new QueryConditionAnalyzer(); private QueryConditionAnalyzer() {} public static QueryConditionAnalyzer getInstance() { return instance; } }
还有一个使用静态内部类实现单例的:
public class MyCATSequnceProcessor { private static class InnerMyCATSequnceProcessor{ private static MyCATSequnceProcessor INSTANCE = new MyCATSequnceProcessor(); } public static MyCATSequnceProcessor getInstance(){ return InnerMyCATSequnceProcessor.INSTANCE; } }