博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java单例模式再加强——按组多单例
阅读量:6232 次
发布时间:2019-06-21

本文共 2706 字,大约阅读时间需要 9 分钟。

  最近要使用alibaba的rocket mq(我们公司对其进行了封装,使其运行在dotNet平台上,Java还是和原生的差不多,涉及公司的内容本文不会提及),其中 在生产者组这一块,建议是用单例模式的。但是其中又建议一个组(group)使用一个实例,这样仅仅单例模式就不行了,所以要进行改动,我们的目标就是“一个group使用一个单例”。

  其实简单点,多封装几个不同的单例类就行了,一个组用一个类。但是这显然不是一个好主意,于是我们来考虑用另一种方式。

  首先要将 group 这个概念抽出来,它是变量,接下来封装不变的代码。

  我们先看看代码是什么样的:

/** * TurboMQ 消息生产者管理器 */public class MqProducer {    private DefaultMQProducer currentMQProducer;    private static Map
producerMap = new ConcurrentHashMap<>(3); private static final Object lock = new Object(); private MqProducer(String group) throws MQClientException { if (!Validator.isNotNullAndVisible(group)) { throw new NullPointerException("Group名称不能为空!"); } currentMQProducer = new DefaultMQProducer(group); currentMQProducer.setNamesrvAddr(“1.1.1.1”); currentMQProducer.start(); } public static MqProducer instance(String group) throws MQClientException { if (!Validator.isNotNullAndVisible(group)) { throw new NullPointerException("Group名称不能为空!"); } if (producerMap.get(group) == null) { synchronized (lock) { if (producerMap.get(group) == null) { producerMap.put(group, new MqProducer(group)); } } } return producerMap.get(group); } public SendResult send(String topic, String tag, String body) throws UnsupportedEncodingException, InterruptedException, RemotingException, MQClientException, MQBrokerException { if (!Validator.isNotNullAndVisible(topic, tag, body)) { throw new NullPointerException("请检查参数是否为空,topic,tag,body"); } Message message = new Message(topic, tag, body.getBytes("UTF-8")); return currentMQProducer.send(message); } public static void shutdownAll() { producerMap.forEach((key, value) -> { value.shutdown(); }); } public void shutdown() { currentMQProducer.shutdown(); }}

  我们的解决思路,就是使用 Map 让 group 和实例一一对应起来。

  这些代码中你可能需要注意的点是:

    1 线程安全的 ConcurrentHashMap 以及要设置初始容量

private static Map
producerMap = new ConcurrentHashMap<>(3);

    2 instance方法中的两层 if 判断

       在 synchronized(lock)锁住之前可能有多个线程了解到当前组是null,都去请求锁,当第一个线程new了新生产者之后,下一个进程进来就不会再new一个新的生产者了。

public static MqProducer instance(String group) throws MQClientException {        if (producerMap.get(group) == null) {            synchronized (lock) {                if (producerMap.get(group) == null) {                    producerMap.put(group, new MqProducer(group));                }            }        }        return producerMap.get(group);    }

 

  题外话:

    为什么要抛异常?

    因为此处是通用代码,通用代码不应处理业务逻辑,而且不该隐蔽错误的发生,要让业务逻辑去确保参数没问题。

转载地址:http://mlxna.baihongyu.com/

你可能感兴趣的文章
java 账号密码登陆验证码_介绍javaweb登录验证码的实现方法步骤
查看>>
java 上传 分片技术_java 大文件分片上传处理
查看>>
java 平滑 停止_设计Java应用程序的平滑停止
查看>>
java生成8位数随机码_JAVA 生成无重复8位随机码
查看>>
java范围查询treemap_java集合-TreeMap
查看>>
Java解决主从数据库延迟问题_MySQL主从数据库同步延迟问题解决
查看>>
java将jfif格式转换成ipg_jfif是什么格式?Win10将图片JFIF格式转成JPG格式的方法
查看>>
socket.io java 点对点_netty-socket.io点对点通讯和聊天室通讯
查看>>
python java thrift_Apache Thrift PythonJava“连接被拒绝”
查看>>
java测试邮箱是否_javaWEB邮件测试
查看>>
java里booelan_Java Web应用开发技术与案例教程 教学课件 张继军 第4章_JDBC数据库访问技术.ppt...
查看>>
php mysql记录用户行为_用户参与记录存储的演变_PHP教程
查看>>
python中使用缩进来体现代码之间的逻辑关系_Python使用缩进来体现代码之间的逻辑关系。...
查看>>
python图像对比度拉伸_python库skimage 图像直方图均衡化、自适应均衡化、对比度拉伸实现...
查看>>
java判断是不是disable_Java Compiler disable()方法与示例
查看>>
php 发送 二进制,PHP处理二进制数据的实现方法
查看>>
用php写上传文件的代码,php多文件上传实现代码
查看>>
php发送邮件怎么配置,php 配置smtp发送邮件
查看>>
java文件名要和什么一致,Java源程序的文件名一定要与文件中某个类的名称一致。...
查看>>
c php结合,腾讯熊月:企点将php嵌入到高性能C/C++框架运行的探索实践
查看>>