单例模式实战

    xiaoxiao2023-10-23  170

            读最近同学发的一篇文章,单例模式最佳实践:https://www.jianshu.com/p/b08fdc6f86a1 有感。以前学过单例,没有实战经验,并不知道它在程序优化的方面有很大的作用。最近通过一段时间的学习和开发,对单例模式有了更多的了解。

     

                                                                                                                                        ----------不断学习才能跟上大神的脚步。

    单例模式在高并发情况下还需要考虑很多东西,此篇只做自己参考

    应用场景:

    1、数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。

    2、多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。

    3、Windows的Task Manager(任务管理器)就是很典型的单例模式(这个很熟悉吧),想想看,是不是呢,你能打开两个windows task manager吗? 不信你自己试试看哦~

    4、Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。

    实例:(自己加上私有化的构造函数)

    1、利用单例模式连接MongDB

    public class MongoUtils { private MongoUtils(){} private static MongoDBDao componentDao = MongoUtils.getComponentMongDbDao(); public static MongoDBDao getComponentMongDbDao() { // 获取mongo-component数据源,建立MongoDB连接池和MongoDBTemplate等封装的操作 return MongoDB.getMongoDBDao("mongo-component"); } } 2、初始化redis集群工具类 public class GedisUtils { private static GedisCommands gedis; public static volatile GedisCommands getInstance() { if (gedis != null) { return gedis; } log.info("初始化Redis"); try { synchronized (GedisUtils.class) { if (gedis == null) { if (EotBatchProperties.private_deploy) { log.info("开始初始化单点Redis..addr=" + Properties.private_redis_addr); gedis = GedisCommandsFactory.INSTANCE.getRedisCommand(Constant.PRIVATE_REDIS_TAG, Properties.private_redis_addr); } else { log.info("开始初始化Redis集群"); GedisPoolConfig config = new GedisPoolConfig(); config.setMaxTotal(Properties.redis_conn_max_total); gedis = GedisCommandsFactory.INSTANCE.getClusterCommand(Constant.PRIVATE_REDIS_TAG, "", config); } } } } catch (Exception e) { log.error("Gedis初始化过程出错,cause=" + ThrowableUtils.cause(e)); System.exit(1); } return gedis; } } public enum GedisCommandsFactory { INSTANCE; private static ConcurrentHashMap<String, GedisCommands> singlePools = new ConcurrentHashMap(); public GedisCommands getRedisCommand(String tag, String id, GedisPoolConfig poolConfig) { if (id != null && !id.trim().equals("")) { String[] temp = id.trim().split(":"); if (temp.length != 3) { RedisLog.info("非法的参数,id = " + id); return null; } else { String key = GedisConstants.APPCODE + "-" + tag + "-" + id.trim(); GedisCommands proxy = (GedisCommands)singlePools.get(key); if (proxy == null) { proxy = GedisInitialize.getInstance().getSingleCommand(key, new GedisCommandsFactory.RedisConnInfo(tag, id, poolConfig)); if (proxy == null) { return null; } //在此处可以保证单例 GedisCommands currentProxy = (GedisCommands)singlePools.putIfAbsent(key, proxy); if (currentProxy != null) { proxy = currentProxy; } } return proxy; } } else { RedisLog.info("获取redis连接池时id为空"); return null; } } }

     

    3、ZK的连接

    public class ZkClientHolder { private static CuratorFramework client = CuratorFrameworkFactory.builder().defaultData(null) .connectString(ZkProperties.getZkAddress()).retryPolicy(new RetryNTimes(12, 5000)).build(); private static AtomicBoolean startup = new AtomicBoolean(false); private static CountDownLatch countDownLatch = new CountDownLatch(1); private ZkClientHolder(){} public static CuratorFramework getInstance() { return client; } public static void startup() { //仅执行一次 if (startup.compareAndSet(false, true)) { initZkClient(); } } private static void initZkClient() { client.getConnectionStateListenable().addListener(new ConnectionStateListener() { @Override public void stateChanged(CuratorFramework client, ConnectionState newState) { if (newState.isConnected()) { countDownLatch.countDown(); log.info("Zookeeper连接成功"); } else { log.error("Zookeeper连接丢失,重连中..."); } } }); if (client.getState() == CuratorFrameworkState.LATENT) { client.start(); //阻塞直接连接成功或超时 try { if (!countDownLatch.await(60, TimeUnit.SECONDS)) { // 创建连接失败,记录日志并退出应用 log.error("Zookeeper连接创建失败,超时,退出应用"); System.exit(1); } } catch (InterruptedException e) { log.error("Zookeeper连接动作被中断,退出应用"); System.exit(1); } } else if (client.getState() == CuratorFrameworkState.STOPPED) { log.error("Zookeeper连接创建失败,连接已关闭,退出应用"); System.exit(1); } } }

     

    最新回复(0)