Java单例模式再加强——按组多单例
最近要使用alibaba的rocket mq(我们公司对其进行了封装,使其运行在dotNet平台上,Java还是和原生的差不多,涉及公司的内容本文不会提及),其中 在生产者组这一块,建议是用单例模式的。但是其中又建议一个组(group)使用一个实例,这样仅仅单例模式就不行了,所以要进行改动,我们的目标就是“一个group使用一个单例”。
其实简单点,多封装几个不同的单例类就行了,一个组用一个类。但是这显然不是一个好主意,于是我们来考虑用另一种方式。
首先要将 group 这个概念抽出来,它是变量,接下来封装不变的代码。
我们先看看代码是什么样的:
/**
* TurboMQ 消息生产者管理器
*/
public class MqProducer { private DefaultMQProducer currentMQProducer; private static Map<String, MqProducer> 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<String, MqProducer> 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);
}
题外话:
为什么要抛异常?
因为此处是通用代码,通用代码不应处理业务逻辑,而且不该隐蔽错误的发生,要让业务逻辑去确保参数没问题。
Java单例模式再加强——按组多单例的更多相关文章
- Java线程和多线程(五)——单例类中的线程安全
单例模式是最广泛使用的创建模式之一.在现实世界之中,诸如Databae的连接或者是企业信息系统(EIS)等,通常其创建都是受到限制的,应该尽量复用已存在对象而不是频繁创建销毁.为了达到这个目的,开发者 ...
- JAVA笔记5__构造块、静态块/单例设计模式/继承/final关键字/super关键字
public class Main { { //构造块(在构造对象时调用,先于构造方法执行) System.out.println("我是构造块!"); } static{ //静 ...
- Java面向对象 Main函数 静态的应用 单例设计模式
Java面向对象 Main函数 静态的应用与单例设计模式 知识概要 (1)Main函数的细解 (2)静态的应用,静态变量,静态代码块,静态函数 (3)单例设计模式 1.M ...
- Java静态变量的用法:伪单例
这几天遇到一个问题,一个Service里有一个map,但是这个Service有别的继承,于是每一个Service都会创建一个map,但是这个map应该是公用的,于是就有问题了...(按结构说Servi ...
- Spring单例Bean和线程安全
Spring的bean默认都是单例的,这些单例Bean在多线程程序下如何保证线程安全呢?例如对于Web应用来说,Web容器对于每个用户请求都创建一个单独的Sevlet线程来处理请求,引入Spring框 ...
- Java 单例模式详解
概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. ...
- 0013 Java学习笔记-面向对象-static、静态变量、静态方法、静态块、单例类
static可以修饰哪些成员 成员变量---可以修饰 构造方法---不可以 方法---可以修饰 初始化块---可以修饰 内部类(包括接口.枚举)---可以修饰 总的来说:静态成员不能访问非静态成员 静 ...
- 转 java 类 单例
转 单例概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一 ...
- Java单例模式深入详解
原文地址:http://www.cnblogs.com/hxsyl/ 仅作为笔记收藏…… 一.问题引入 偶然想想到的如果把Java的构造方法弄成private,那里面的成员属性是不是只有通过stati ...
随机推荐
- Jenkins添加用户
新建用户 Jenkins刚开始的界面是允许访客进行所有操作的,这时Jenkins是有安全隐患的,也不容易去管理.这时,我们需要管理Jenkins的权限,对它的权限进行设置.关于Jenkins权限设置的 ...
- c#入门系列——类和对象的代码实现
面向对象 说起面向对象,大家因该都听说过,也知道是一个编程的方法,简称oop技术.它将对象的算法和数据结构看作一个整体,而一个程序就是由多个对象结合的整体.这样做可以提高代码的复用率,提高了软件的可维 ...
- Cookie与Passport安全
对于web系统而言,由于HTTP协议无状态的特性,用户登录时需要服务端生成通行证返回给浏览器.浏览器保存该通行证并在接下来的请求中携带该通行证.通常来讲,web系统使用http cookie来保存和传 ...
- 用jdk在cmd下运行编译java程序
1.首先通过创建一个txt文档,将java代码写入txt文档中保存 2.将保存好的HelloWorld.txt文档重命名为HelloWorld.java文件. 3.打开windows中的"命 ...
- 蓝牙门禁Android客户端
先来了解下Android传统蓝牙连接的大致简单的流程: 其中涉及到几个类依次来介绍,废话不多说,下面是从Android4.4开发指南蓝牙所用到的类的截图: 第一个类BluetoothAdapter: ...
- js获取浮动(float)元素的style.left值为空的解决办法
解决办法: 1.使用行内样式设置元素的top和left值; 2.or直接获取元素的offsetLeft得到相关数值,还不需要parseInt 问题原因: 如果父div的position定义为relat ...
- 游戏UI框架设计(二) : 最简版本设计
游戏UI框架设计(二) --最简版本设计 为降低难度决定先讲解一个最简版本,阐述UI框架的核心设计理念.这里先定义三个核心功能: 1:UI窗体的自动加载功能. 2:缓存UI窗体. 3:窗体生命周期(状 ...
- oracle 随笔
oracle分页 select * from (select a1.*, rownum rn from (select *from emp) a1 where rownum<=10) where ...
- 复制vmware中的centos后无法上网问题
复制vmware中的centos后无法上网问题 查看IP命令 ip addr 网卡信息 eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000 使用的是e ...
- BZOJ 1198: [HNOI2006]军机调度(搜索)
直接暴搜就行了= = CODE: #include<cstdio> #include<iostream> #include<cstring> #include< ...