launchConfig - 创建queueDispatcher,调其init-method: start- 起线程- 在线程里死循环getMsg,–再放线程池里,再发送
都是同一个消息队列,linkedBlockingQueue(由spring管理,单例) , set 和 get
set时候,起线程池往queue里add,
下面上代码:
1、线程池,往队列里插消息
public void pushToAllDeviceWithParams(PushRequest request) throws PushServiceException {
if (StringUtils.isEmpty(request.getTitle()) || StringUtils.isEmpty(request.getContent())) {
throw new PushServiceException("title或者content不能为空");
}
POOL.execute(new BroadcastPushHandler(request));
}
public void run() {
PushMessage msg = saveMsg(request, delay(request));
if (StringUtils.isEmpty(msg.getScheduleTime())) {
realTimeQueue.add(msg.getId());
} else {
scheduleQueue.add(msg.getId() + "," + msg.getScheduleTime());
}
}
注意这个queue,是spring注入的,即单例,后面消费者会用到。LinkedBlockingQueue的特性应该要清楚,这里用到的生产消费方法都是会阻塞的那种:add, take。
@Autowired
private RealTimeQueue realTimeQueue;
且queue是用的linkedBlockingQueue,队列里放的是消息ID
@Component
public class RealTimeQueue {
private final LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();
/**
* 增加
* @param id id
*/
public void add(String id) {
if (!queue.contains(id)) {
queue.add(id);
}
}
/**
* 获取
* @return string
* @throws InterruptedException 异常
*/
public String get() throws InterruptedException {
return queue.take();
}
}
2、取消息并发送
先起个线程
/**
* 启动器
*/
public void start() {
LOGGER.info("queue dispatcher started!");
new Thread(new RTThread()).start();
new Thread(new ScheduleThread()).start();
}
在此线程里,死循环获取消息
private class RTThread implements Runnable {
/**
* 主函数
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
LOGGER.info("RTThread started!");
while (true) {
try {
String msgId = realTimeQueue.get();
POOL.submit(new PusherCaller(msgId));
} catch (Exception ex) {
LOGGER.error(ex.getMessage(), ex);
}
}
}
}
获取到之后,再起线程池去发送: POOL.submit(new PusherCaller(msgId));
发送的时候,会用消息ID查出实体,再看实体的类型,决定是广播还是单播。
private final class PusherCaller implements Callable<Object> {
private String msgId;
/**构造函数
* @param msgId id
*/
private PusherCaller(String msgId) {
this.msgId = msgId;
}
/**
* 主函数
* @see java.util.concurrent.Callable#call()
*/
@Override
public Object call() throws Exception {
PushMessage msg = null;
try {
msg = pushMessageDAO.getMsgById(msgId);
} catch (Throwable ex) {
LOGGER.error(ex.getMessage(), ex);
}
if (msg != null) {
if (MessageType.ALL.getType().equals(msg.getMsgType())) {
if (PushConfig.getNeedTencent()) {
PushObject tencent = new PushObject();
tencent.setChannel(Channel.TENCENT.getChannel());
tencent.setMessage(msg);
pusher.pushAll(tencent);
}
PushObject po = new PushObject();
po.setChannel(Channel.BAIDU.getChannel());
po.setMessage(msg);
pusher.pushAll(po);
return null;
} else if (MessageType.SINGLE.getType().equals(msg.getMsgType())) {
List<Map<Object, Object>> list = pushMessageDAO.getUserPushBindsByMsgId(msgId);
if (list.isEmpty()) {
return null;
}
for (Map<Object, Object> map : list) {
String token = String.valueOf(map.get("token"));
String baiduId = String.valueOf(map.get("baiduId"));
String device = String.valueOf(map.get("device"));
LOGGER.info("baiduId:" + baiduId + "..............device:" + device);
//
if (PushConfig.getNeedTencent()) {
SinglePushObject tencent = new SinglePushObject();
tencent.setChannel(Channel.TENCENT.getChannel());
tencent.setMessage(msg);
tencent.setChannelId(baiduId);
tencent.setDevice(Integer.valueOf(device));
pusher.pushSingle(tencent);
continue;
}
if (StringUtils.isEmpty(baiduId)) {
continue;
}
LOGGER.info(">>>>>>获取未读消息:");
Integer unreads = getUnreads(msgId, Integer.valueOf(device));
SinglePushObject po = new SinglePushObject();
po.setDevice(Integer.valueOf(device));
po.setChannel(Channel.BAIDU.getChannel());
po.setMessage(msg);
po.setChannelId(baiduId);
po.setUnreads(unreads);
pusher.pushSingle(po);
}
} else if (MessageType.BATCH.getType().equals(msg.getMsgType())) {
List<Map<Object, Object>> list = pushMessageDAO.getUserPushBindsByMsgId(msgId);
List<String> tokens = new ArrayList<String>();
List<String> baidusIos = new ArrayList<String>();
List<String> baidusAndroid = new ArrayList<String>();
Integer device = msg.getPushDevice();
for (Map<Object, Object> map : list) {
String token = String.valueOf(map.get("token"));
String baiduId = String.valueOf(map.get("baiduId"));
if (!StringUtils.isEmpty(baiduId)) {
String userDevice = String.valueOf(map.get("device"));
if (Integer.valueOf(userDevice) == PushDevice.ANDROID.getDevice()) {
if (device == PushDevice.ALL.getDevice() || device == PushDevice.ANDROID.getDevice()) {
baidusAndroid.add(baiduId);
LOGGER.info("batch.....device...." + userDevice);
}
} else if (Integer.valueOf(userDevice) == PushDevice.IOS.getDevice()) {
if (device == PushDevice.ALL.getDevice() || device == PushDevice.IOS.getDevice()) {
baidusIos.add(baiduId);
LOGGER.info("batch.....device...." + userDevice);
}
}
continue;
}
if (!StringUtils.isEmpty(token)) {
tokens.add(token);
}
}
if (PushConfig.getNeedTencent() && !tokens.isEmpty()) {
BatchPushObject tencent = new BatchPushObject();
tencent.setChannel(Channel.TENCENT.getChannel());
tencent.setMessage(msg);
tencent.setChannelIds(tokens);
pusher.pushBatch(tencent);
}
if (!baidusAndroid.isEmpty()) {
BatchPushObject po = new BatchPushObject();
po.setChannel(Channel.BAIDU.getChannel());
po.setMessage(msg);
po.setChannelIds(baidusAndroid);
po.setDevice(PushDevice.ANDROID.getDevice());
pusher.pushBatch(po);
}
if (!baidusIos.isEmpty()) {
for (String baiduId : baidusIos) {
Integer unreads = getUnreads(msgId, Integer.valueOf(device));
SinglePushObject po = new SinglePushObject();
po.setDevice(PushDevice.IOS.getDevice());
po.setChannel(Channel.BAIDU.getChannel());
po.setMessage(msg);
po.setChannelId(baiduId);
po.setUnreads(unreads);
pusher.pushSingle(po);
}
}
} else {
LOGGER.error("unrecognized MessageType:" + msg.getMsgType() + " with msgId:" + msgId);
}
}
return null;
}